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.
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.
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
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.
LispWorks User Guide and Reference Manual - 20 Sep 2017