On Fri, May 01, 2026 at 06:26:11PM +0800, Qian Yun wrote:
> Current ')set message storage on' can report the total memory
> usage, but it can't report the memory recycled by GC.
>
> For a certain computation, there is memory needed by the result,
> and memory allocated by temporary objects and can be recycled later.
>
> This stat of "memory recycled by GC" can be a useful indicator,
> to tell if the algorithm is memory efficient.
>
> The typical use should be this, do a GC first, then the computation
> and a GC after that.
Look nice, go on.
> - Qian
>
> (1) -> )set message storage on
> (1) -> RECLAIM()$Lisp
>
> (1) ()
> Type: SExpression
> Storage: 2,249,056 (OT) = 2,249,056 bytes (185,008 bytes
> recycled)
> (2) -> [x for x in 1..100000]; RECLAIM()$Lisp
>
> (2) ()
> Type: SExpression
> Storage: 133,589,184 (EV) = 133,589,184 bytes (132,395,504 bytes
> recycled)
>
> --
> 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
fricas-devel...@googlegroups.com.
> To view this discussion visit
https://groups.google.com/d/msgid/fricas-devel/a64d8f3a-214e-4bed-9fe8-0f970596e5d4%40gmail.com.
> diff --git a/src/interp/g-timer.boot b/src/interp/g-timer.boot
> index 11f8415e..76c1fafd 100644
> --- a/src/interp/g-timer.boot
> +++ b/src/interp/g-timer.boot
> @@ -50,6 +50,9 @@ makeLongStatStringByProperty _
> for [name,class,:ab] in listofnames repeat
> n := statsVec.(GET(name, 'index))
> classStats.class := classStats.class + n
> + -- GC time should be counted into total time,
> + -- but space recycled by GC should not be counted into total space
> + name = 'gc and property = 'SpaceTotal => 'iterate
> total := total + n
> name = 'other or flag ~= 'long => 'iterate
> if significantStat? n then
> @@ -60,11 +63,16 @@ makeLongStatStringByProperty _
> str := makeStatString(str, otherStatTotal + insignificantStat, 'other, flag)
> else
> for [class,name,:ab] in listofclasses repeat
> + name = 'reclaim and property = 'SpaceTotal => 'iterate
> n := classStats.class
> str := makeStatString(str, n, ab, flag)
> total := STRCONC(normalizeStatAndStringify total,'" ", units)
> - str = '"" => total
> - STRCONC(str, '" = ", total)
> + if str ~= '"" then total := STRCONC(str, '" = ", total)
> + if property = 'SpaceTotal then
> + n := statsVec.(GET('gc, 'index))
> + if n ~= 0 then
> + total := STRCONC(total, FORMAT(nil, '" (~:d bytes recycled)", n))
> + total
>
> normalizeStatAndStringify t ==
> FLOATP t =>
> @@ -158,16 +166,18 @@ initializeTimedStack() ==
> $timedNameStack := '(other)
> len := # $interpreterTimedNames
> $statsInfo := VECTOR(MAKEARR1(len, 0), MAKEARR1(len, 0), get_run_time(), _
> - elapsedGcTime(), HEAPELAPSED())
> + elapsedGcTime(), HEAPELAPSED(), current_heap_size())
> NIL
>
> updateTimedName name ==
> oldTime := $statsInfo.2
> oldGCTime := $statsInfo.3
> oldSpace := $statsInfo.4
> + oldHeap := $statsInfo.5
> newTime := $statsInfo.2 := get_run_time()
> newGCTime := $statsInfo.3 := elapsedGcTime()
> newSpace := $statsInfo.4 := HEAPELAPSED()
> + newHeap := $statsInfo.5 := current_heap_size()
>
> i := GET(name, 'index)
> timeVec := $statsInfo.0
> @@ -177,6 +187,7 @@ updateTimedName name ==
> i2 := GET('gc, 'index)
> timeVec.i2 := timeVec.i2 + gcDelta * $inverseTimerTicksPerSecond
> spaceVec.i := spaceVec.i + newSpace - oldSpace
> + spaceVec.i2 := spaceVec.i2 + newSpace - newHeap - (oldSpace - oldHeap)
>
> makeLongTimeString(listofnames,listofclasses) ==
> makeLongStatStringByProperty(listofnames, listofclasses, _
> diff --git a/src/interp/macros.lisp b/src/interp/macros.lisp
> index fc5265b4..1137dafb 100644
> --- a/src/interp/macros.lisp
> +++ b/src/interp/macros.lisp
> @@ -387,6 +387,20 @@ This function respects intermediate #\Newline characters and drops
> #-(or :clisp :cmu :ecl :openmcl :sbcl :lispworks)
> 0)
>
> +(defun |current_heap_size| ()
> + #+:clisp
> + (nth-value 0 (sys::%room))
> + #+:cmu
> + (lisp::dynamic-usage)
> + #+:lispworks
> + (getf (system:room-values) :total-allocated)
> + #+:openmcl
> + (nth-value 0 (ccl::%usedbytes))
> + #+:sbcl
> + (sb-kernel:dynamic-usage)
> + #-(or :clisp :cmu :lispworks :openmcl :sbcl)
> + 0)
> +
> (defun |goGetTracerHelper| (dn f oname alias options modemap)
> (lambda(&rest l)
> (|goGetTracer| l dn f oname alias options modemap)))
--
Waldek Hebisch