The function make-current-allocation-permanent
makes all the objects currently allocated in generation 2 permanent, which means that they will never be GCed.
If gc-p is non-nil (the default) then make-current-allocation-permanent
does an initial GC by calling (gc-generation 2 :coalesce
coalesce)
, which by default means that all currently live objects are promoted to generation 2, and hence are made permanent. coalesce defaults to t
. See the documentation for gc-generation for details.
For Static objects, only segments that are in generation 2 are made permanent (because static objects are never promoted between generations).
The function generation-number returns 3 when its argument is a permanent object. room reports the Other and Cons objects that were made permanent under Permanent Other and Permanent Cons, except Large and Static, where (room t)
reports permanent segments as being in generation 3.
Making objects permanent saves work for the GC, but wastes some memory. Repeated calls to make-current-allocation-permanent
wastes more memory. The operation itself is fast, but the initial GC takes time depending on the amount allocated.
The operation is done by moving whole segments to the permanent segments, which means that any free area in the segments is moved as well and hence is wasted (permanently). It is therefore essential to reduce the free area in generation 2 before calling make-current-allocation-permanent
by performing a GC of generation 2. Hence you should pass gc-p nil
only if you already did the GC of generation 2 explicitly.
Passing coalesce nil
means that currently live objects in generation 0 are not made permanent. This is useful for objects that are short-lived, but will cause young long-lived objects to stay in the GCed generations. The effect either way is unlikely to be large.
Note also that since permanent objects are not GCed, a permanent object that points to a non-permanent one will keep the non-permanent object live forever (unless the pointer is overwritten explicitly by the application). That will make the non-permanent object live forever as well, and hence add work for the GC.
The main effect of making objects permanent is to reduce the time and the memory peak required for GC of generation 2, so can have a very beneficial effect on performance. It is particularly useful if the relatively few objects are allocated after the call that live forever, so the size of generation 2 after a GC of generation 2 is relatively small. Using make-current-allocation-permanent
is probably useful even if 20% of the permanent objects would have died after a while if left in the GCable generations. If the application does not create new permanent objects, but does have objects that live long enough to be promoted to generation 2 before dying ("generation leak"), it maybe useful to call make-current-allocation-permanent
even if 50% of the objects would have died otherwise. These percentages should only be used as a guide.
make-current-allocation-permanent
wastes the memory that is free in generation 2 before the operation. The amount of free memory after the initial GC is typically independent of the amount allocated, and averages around 8 MB. Thus it is not useful to use make-current-allocation-permanent
unless you have significantly more than 8 MB of permanent objects. The waste happens on each call to make-current-allocation-permanent
, so you should minimize the number of calls and typically call it once in a run of the application.
The amount wasted in the permanent areas is the amount that room reports as free under Permanent Cons and Permanent Other, plus the size of the objects in these areas that are effectively dead (not pointed by any other live object). Since the GC does not collect the permanent objects, there is no easy way to know which of them are effectively dead. If you want to know that, you need to run the application without calling make-current-allocation-permanent
, see how much is allocated in generation 2 in this case, and compare this to the amount allocated permanently when you do call make-current-allocation-permanent
.
Large objects (currently that means larger than 1 MB) can be made permanent individually by make-object-permanent and make-permanent-simple-vector, and can be explicitly released and the memory returned to the operating system by using release-object-and-nullify.
gc-generation
make-object-permanent
make-permanent-simple-vector
release-object-and-nullify
Preventing/reducing GC of generation 2
Mobile GC technical details
LispWorks User Guide and Reference Manual - 20 Sep 2017