Some applications periodically free (that is, stop using) a substantial amount of data that lived for long enough to reach generation 2 (use
room
or
sys:room-values
and
sys:generation-number
to follow the behaviour of objects). In this case,
mark-and-sweep
should be called on generation 2, to collect these data and re-use the memory. Repeated cycles like this may cause fragmentation, which will slow down promotion into generation 2. This manifests itself in significant pauses, typically of a few seconds.
try-move-in-generation
or
try-compact-in-generation
can be used to reduce the fragmentation, and hence to reduce the pauses. Because these functions themselves take some time, they should be called when such a pause is acceptable.
'Moving' a segment means moving objects out of the segment to another segment, leaving the segment empty. This reduces the fragmentation in the generation, and it is normally much faster than compact. Therefore in almost all cases,
try-move-in-generation
is better than
try-compact-in-generation
.
The actual decision to use these functions will be typically based on the results of
check-fragmentation
. For example, the following function checks if there is more than 10Mb free area in generation 2 in blocks of 4096 bytes or larger (tlb, third return value of
check-fragmentation
). If there is not, and the free area in generation 2 (tf) is more than four times the free area in large blocks, it calls
try-move-in-generation
. Because
try-move-in-generation
gets a time-threshold of 0, it returns after doing at most one segment. (It won't do any segments if none of them looks fragmented.)
(defun call-memory-functions()
(mark-and-sweep 2) ; first collect all dead objects
(multiple-value-bind (tf tsb tlb)
(check-fragmentation 2) ; check the fragmentation
(when (and (> 10000000 tlb)
(> (ash tf -2) tlb))
(try-move-in-generation 2 0))))
A function such as this can be called at times when a pause of a few seconds is acceptable, and it will keep the memory of generation 2 unfragmented.
It is not possible to give definitive guidance here on how to use
try-move-in-generation
or
try-compact-in-generation
, because it depends on the way the application uses memory. In general, these functions will always improve the behavior of the application. Therefore the main problem is to identify points in the execution of the application where they can be called without causing unacceptably long pauses.