New Garbage Collection features in Allegro CL 10.0

Allegro CL 10.0 has a new garbage collection implementation. The basic design is unchanged: the heap is divided into two newspaces and an indeterminate number of oldspaces. Regular scavenges clear garbage out of newspace using a stop and copy algorithm, and objects that survive a specified (initially 4) scavenges are tenured to oldspace. Oldspaces are gc'ed during global gc's only, using a mark and sweep algorithm.

New in 10.0 are:

  1. The garbage collector can use multiple processors to perform its work, if they are available. See Using multiple processors for garbage collecting below for more information.
  2. The garbage collector has better information on pointers on the stack so objects which are actually dead can be gc'ed. See Precise gc's of the stack below for more information.
  3. The garbage collector can optionally skip portions of a global garbage collection if the space recovered is too small. See Assessing whether some global gc phases are needed below for more information.

The garbage collector is described in gc.htm.

While you can tune the garbage collector for optimizing use of multiple processes, no user action is necessary to get the benefits of the new features.

The user interface has also changed. The function sys:gc-parameters returns (or prints) information about aspects of the gc setup. The related sys:gc-parameter returns information about specific parameters and sys:gc-switch returns information about gc switches. Where appropriate, they can be used with setf to reset values. These functions replace the older sys:gsgc-parameters, sys:gsgc-switch, and sys:gsgc-parameter.

Using multiple processors for garbage collecting

The garbage collector can use multiple threads for global gc's. This is true even in non-SMP Lisps. (Except on the Solaris platform, which does not support either SMP or multi-threaded gc's.) When extra cores are available, this can have a significant effect on the speed of global gc's.

Initially, up to four cores can be used for gc'ing. The gc parameters :thread-limit specifies how many cores can be used (see sys:gc-parameters and sys:gc-parameter). Users who have a lot of cores and no reason to keep any free for other tasks (like display or background tasks) might increase the number to get shorter pause times. Users who have few cores or important background tasks might want to decrease it. Setting it to 1 means that gc's will always use 1 thread only. Users might vary the value to see what effect it has on pause times.

See Using multiple threads in global gc's in gc.htm for further information.

Precise gc's of the stack

Because some Lisp values exist on the stack, the garbage collector must scan the stack to determine whether there are valid pointers to objects. A valid pointer to an object indicates the object is not garbage.

However, some values on the stack which look like valid pointers may not be. When a variable is placed on the stack or when the stack pointer is moved so the stack is larger, values are not initialized (since doing so would slow down executaion time noticeably). During a gc (scavenge or global), the stack is scanned and pointers are examined. Some do not point to Lisp values. Those are leftovers and can be ignored. But some point to valid Lisp objects. These might be valid live objects but they may also be dead Lisp objects suitable for gc'ing, the pointer on the stack coming from an uninitialized value just added or uncovered.

In releases prior to 10.0, the garbage collector took a conservative approach: a pointer to a Lisp object was always assumed to be valid and so the object was assumed to be live (i.e. not garbage). Starting in release 10.0, Lisp keeps precise information on most pointers on teh stack and so it can distinguish between valid ones and one simply uncovered by variable assignment or a stack pointer move. This precise information allows for many more Lisp objects which are actually garbage to be removed during a gc.

The conservative approach is still used in some case, such as when when the system considers it likely the function is being debugged (because it has stopped at an unexpected place), or when information on the frame is insufficient to tell whether pointers in it should be considered, or when determining whether the frame should be considered will itself take too much time. But the precise approach is used whenever possible and is the typical approach used. See Precise gc's of the stack in gc.htm for further information.

Assessing whether some global gc phases are needed

The last two phases of a global garbage collection are adjustment and compactification. These phases take a significant portion of the global gc time. Now the amount of space that will be recovered from those operations can be estimated, in a process known as reward assessment. If the estimate is less than the value of the :min-global-recovery parameter, those phases are skipped. This can result in a significant time saving. See Assessing whether the adjustment and compactification phases are justified in gc.htm for further information.

As we said above, no user action is necessary to get the benefits or using multiple cores for gc's, although you can tune how many cores should be used. There is no user control at all over using the conservative versus the precise method for scanning the stack. There is a positive initial value of the :min-global-recovery parameter, and users may wish to play with value to see whether a larger or smaller value has a beneficial effect. In general, the changes should be more or less invisible to users except gc's should in general be faster. Again, the garbage collector is described in gc.htm. Users who have questions about the new gc scheme or who have any problems should contact support at support@franz.com.

Copyright © 2023 Franz Inc., All Rights Reserved | Privacy Statement Twitter