[elephant-cvs] CVS elephant/src/elephant

ieslick ieslick at common-lisp.net
Tue Sep 5 03:23:18 UTC 2006


Update of /project/elephant/cvsroot/elephant/src/elephant
In directory clnet:/tmp/cvs-serv10674/src/elephant

Modified Files:
	serializer.lisp variables.lisp 
Log Message:
Extended thread support in thread-safe serializer to other lisps

--- /project/elephant/cvsroot/elephant/src/elephant/serializer.lisp	2006/09/04 05:01:06	1.11
+++ /project/elephant/cvsroot/elephant/src/elephant/serializer.lisp	2006/09/05 03:23:17	1.12
@@ -60,25 +60,75 @@
 (defconstant +fill-pointer-p+     #x40)
 (defconstant +adjustable-p+       #x80)
 
+;;
+;; This may be overkill, but is intended to avoid continually allocating
+;; hashes each time we serialize an object.  I added some adaptation
+;; to keep it from dropping and re-allocating if the user continually saves
+;; large collections of objects.  However the defaults should handle most
+;; apps just fine.  The queue is useful because a system with 10 threads
+;; will need 10 circularity queues if it is storing large objects
+;;
+
 (defvar *circularity-hash-queue* nil
   "Circularity ids for the serializer.")
 
+;; quick portability hack, do we need to import 'port' or some
+;; other thread layer to the elephant dependency list?
+
+(defun ele-make-lock ()
+  #+allegro (mp::make-process-lock)
+  #+cmu (mp:make-lock)
+  #+sbcl (sb-thread:make-mutex)
+  #+mcl (ccl:make-lock)
+  #+lispworks (mp:make-lock)
+  #-(or allegro sbcl cmu lispworks mcl) nil )
+
+(defmacro ele-with-lock ((lock) &body body)
+  #+allegro `(mp:with-process-lock (,lock) , at body)
+  #+cmu `(mp:with-lock-held (,lock) , at body)
+  #+sbcl `(sb-thread:with-mutex (,lock) , at body)
+  #+lispworks `(mp:with-lock (,lock) , at body)
+  #+mcl `(ccl:with-lock-grabbed (,lock) , at body)
+  #-(or allegro sbcl cmu lispworks mcl) `(progn , at body) )
+
 (defvar *circularity-lock*
-  #+allegro (mp::make-process-lock))
+  (ele-make-lock))
+
+(defun drop-circularity-hash-p (hash)
+  "This allows us to tune our memory usage to the application.
+   If grow-ceiling-p is enabled then we'll slowly adapt to 
+   a growing demand so we balance GC load and reserved memory"
+  (if (> (hash-table-size hash) *circularity-max-hash-size*)
+      (if (and *circularity-grow-ceiling-p*
+	       (>= (incf *circularity-adapt-count*)
+		   *circularity-adapt-step-size*))
+	  (progn 
+	    (setf *circularity-max-hash-size*
+		  (ceiling (* *circularity-growth-factor*
+			      *circularity-max-hash-size*)))
+	    nil)
+	  t)
+      (progn
+	(decf *circularity-adapt-count* 0.5)
+	nil)))
 
 (defun get-circularity-hash ()
-  (if *circularity-hash-queue*
-      (#+allegro 
-       mp::with-process-lock (*circularity-lock*)
-       (pop *circularity-hash-queue*))
-      (make-hash-table :test 'eq :size 50)))
+  (if (not *circularity-hash-queue*)
+      (make-hash-table :test 'eq :size 50)
+      (if *circularity-lock*
+	  (ele-with-lock (*circularity-lock*)
+	    (pop *circularity-hash-queue*))
+	  (pop *circularity-hash-queue*))))
 
 (defun release-circularity-hash (hash)
-  (unless (> (hash-table-size hash) 100)
+  (unless (drop-circularity-hash-p hash)
     (clrhash hash)
-    (#+allegro 
-     mp::with-process-lock (*circularity-lock*)
-     (push hash *circularity-hash-queue*))))
+    (if *circularity-lock*
+	(ele-with-lock (*circularity-lock*)
+	  (push hash *circularity-hash-queue*))
+	(push hash *circularity-hash-queue*))))
+
+
 
 (defun serialize (frob bs)
   "Serialize a lisp value into a buffer-stream."
--- /project/elephant/cvsroot/elephant/src/elephant/variables.lisp	2006/09/04 00:09:15	1.3
+++ /project/elephant/cvsroot/elephant/src/elephant/variables.lisp	2006/09/05 03:23:17	1.4
@@ -43,6 +43,29 @@
    Users attempting to directly write this variable will run into an
    error")
 
+;;;;;;;;;;;;;;;;;
+;;;; Serializer optimization parameters
+
+(defvar *circularity-initial-hash-size* 50
+  "This is the default size of the circularity cache used in the serializer")
+(defvar *circularity-max-hash-size* 100
+  "This is the largest hash table that is maintained by the serializer.  Larger
+   hash tables are dropped from the has queue assuming that it was a one of 
+   transaction or an error.")
+(defparameter *circularity-grow-ceiling-p* t
+  "This enables the system to slowly adapt to larger-than-average lists or other 
+   collections of objects (like large trees) to avoid continually GC'ing large
+   data structures and reducing total copying over time")
+(defparameter *circularity-adapt-step-size* 4
+  "How many times we see something over the max in succession before we adapt
+   to a larger maximum size")
+(defparameter *circularity-growth-factor* 0.5
+  "How much to increase the max size after each adaptation step")
+(defvar *circularity-adapt-count* 0
+  "Maintains a count of how many times we've seen a hash table over the appropriate
+   size.  This is reduced by 1/2 each time we don't have one that is oversized.")
+
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Thread-local specials
 




More information about the Elephant-cvs mailing list