On 5/10/26 10:50 PM, Qian Yun wrote:
> 
> But we can have the best of both worlds: when the array cache
> needs to expand (or hitting some threshold, or triggered manually),
> use sb-ext:make-weak-pointer on the kernels, do a GC,
> create the smaller cache again.  I'll report back.
> 
> - Qian
> 

Naively using weak pointer will get trouble, this might also
explain the errors met by the previous hashtable approach:
say you are doing integrals, the program may just construct
a useful kernel, and enter it to cache, but it is not referenced
by any expression, then it can get recycled by GC, causing
failures later.

I wonder if it is safe to recycled kernels at top level
interpreter, manually, between 2 commands.  If so, we can
automate the process by running this kernel recycle function
via something like a hook.

In the attachment is my draft version, I haven't tested it
extensively yet.

- Qian

-- 
You received this message because you are subscribed to the Google Groups 
"FriCAS - computer algebra system" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/fricas-devel/ebb4184c-1d4c-45fd-9aa7-a0fec7743fab%40gmail.com.
diff --git a/src/algebra/kl.spad b/src/algebra/kl.spad
index 0365b60f..1d39498a 100644
--- a/src/algebra/kl.spad
+++ b/src/algebra/kl.spad
@@ -28,6 +28,8 @@ SortedCache(S : CachableSet) : Exports == Implementation where
   Exports ==> with
     clearCache  : () -> Void
       ++ clearCache() empties the cache.
+    getCache : () -> PrimitiveArray S
+    compactCache : () -> Void
     enterInCache : (S, S -> Boolean) -> S
       ++ enterInCache(x, f) enters x in the cache, calling \spad{f(y)} to
       ++ determine whether x is equal to y. It returns x with an integer
@@ -55,6 +57,15 @@ SortedCache(S : CachableSet) : Exports == Implementation where
     cache : PrimitiveArray S := empty()$(PrimitiveArray S)
     cache_size : N := 0
     cache_use : N := 0
+    getCache() == cache
+
+    compactCache() ==
+        cache_size = 0 => void()
+        ocache := cache
+        x := ocache.0
+        cache := new(cache_size, x)$(PrimitiveArray S)
+        cache_use := MAKE_WEAK_ARRAY(cache, ocache, cache_use, x)$Lisp
+        void()
 
     expandCache(x) ==
         if cache_size = cache_use then
diff --git a/src/lisp/primitives.lisp b/src/lisp/primitives.lisp
index 65783b28..0f9b9a42 100644
--- a/src/lisp/primitives.lisp
+++ b/src/lisp/primitives.lisp
@@ -892,3 +892,16 @@
   `(let ((|$BreakMode| '|trapSpadErrors|))
         (declare (special |$BreakMode|))
         (CATCH '|trapSpadErrors| ,form)))
+
+(defun MAKE_WEAK_ARRAY (newarray oldarray size default_element)
+  (dotimes (i size)
+    (setf (aref newarray i) (sb-ext:make-weak-pointer (aref oldarray i)))
+    (setf (aref oldarray i) nil))
+  (sb-ext:gc :full t)
+  (do ((i 0 (1+ i)) (j 0))
+      ((= i size) j)
+    ;; In SortedCache, CachableSet will never be nil, so no multiple-value-bind here
+    (let ((val (sb-ext:weak-pointer-value (aref newarray i))))
+       (if val (progn (setf (aref newarray j) val)
+                      (setq j (1+ j))))
+       (if (> i j) (setf (aref newarray i) default_element)))))

Reply via email to