This section summarizes Memory Management functionality common to all LispWorks 8.0 implementations.
The macro extended-time is useful when timing the Garbage Collector (GC).
Use start-gc-timing, stop-gc-timing and get-gc-timing to time GC operations.
To reduce the size of the whole image, use clean-down.
In 32-bit LispWorks, you can use (clean-down)
or the less aggressive (clean-down nil)
to reduce the image size when the image is much larger than the amount that is allocated. In 64-bit LispWorks there is no need to do that.
(clean-down t)
promotes to generation 3 and tries to reduce the image size, while (clean-down nil)
promotes only to generation 2 and does not reduce the image size. Experience suggests that the latter is actually more useful in most circumstances.
In some circumstances it is important to avoid enlarging the size of the image even temporarily. The common situation is when the operating system signals low memory. In this situation you should use reduce-memory instead of clean-down.
Interned symbols (and their symbol names), and packages, are treated in a special way, because they are assumed to have a long life. They are allocated in the generation specified by the variable *symbol-alloc-gen-num*, which has the initial value 2 in 32-bit LispWorks and 3 in 64-bit LispWorks.
Symbols created with make-symbol or gensym start out in generation 0.
Symbols will be garbage collected if they are no longer accessible (regardless of property lists) but note that in 32-bit LispWorks, if the symbols are in generation 2 then you might need to invoke gc-generation explicitly to collect them in a timely manner.
Stacks are allocated directly in generation 2 because they are relatively expensive to promote. Therefore creating many processes will cause generation 2 to grow, even if these processes are short-lived.
The variable *default-stack-group-list-length* controls the number of stacks that are cached for reuse. Increase its value if your application repeatedly makes and discards more than 10 processes.
To call a function on all objects in the image, use sweep-all-objects.
You may want to perform special actions when certain types of object are garbage collected, using the functions add-special-free-action, flag-special-free-action, flag-not-special-free-action and remove-special-free-action.
For example, when an open file stream is garbage collected, the file descriptor must be closed. This operation is performed as a special action.
Note: You should not rely on special free actions for objects with a high turn-over rate (that is, where many such objects are allocated and they become garbage fairly quickly), because some may not get collected early enough. Either ensure that the cleanup is called elsewhere, or arrange for a GC to happen.
Users of the Foreign Language Interface may want to specify the allocation of static arrays. The recommended way to do this is to call make-array with :allocation
:static
. See for example :lisp-array
in the Foreign Language Interface User Guide and Reference Manual.
Weak arrays and weak hash tables can be used to allow the GC to free objects.
Relevant functions are make-hash-table, set-hash-table-weak, set-array-weak, make-array and copy-to-weak-simple-vector.
For a description of weak vectors see set-array-weak.
This section describes techniques that may improve the performance of your application by reducing the GC's workload.
This is a technique that can be useful when older objects regularly point to newer objects in a lower generation. In such a case, when the lower generation (only) is collected these newer objects will be promoted even if the older objects are not live. All of these objects will not get collected until the higher generation is collected.
This is a general issue with generational garbage collection and, if it causes poor performance in your application, can be addressed along these lines. It is not necessarily a problem in every case where older objects point to newer objects.
For example, suppose you are popping items from a queue represented as a list of conses (or other structures), then you can set the "next" slot of each popped item to nil
.
In the code below, if the queue-head
cons is promoted to generation n, then all the other conses will also be promoted to generation n eventually, until generation n is collected. This happens even after calls to pop-queue
have removed these conses from the queue.
(defstruct queue head tail) (defun push-queue (item queue) (let ((new (cons item nil))) (if (queue-head queue) (setf (cdr (queue-tail queue)) new) (setf (queue-head queue) new)) (setf (queue-tail queue) new))) (defun pop-queue (queue) (pop (queue-head queue)))
The fix is to make pop-queue
set the "next" slot (in this case the cdr) of the discarded queue-head
cons to nil
, so that it no longer points from an older object to a newer object. For example:
(defun pop-queue (queue) (when-let (head (queue-head queue)) (setf (queue-head queue) (shiftf (cdr head) nil)) (car head)))
LispWorks® User Guide and Reference Manual - 01 Dec 2021 19:30:20