Long-lived data is data that lives long enough to be promoted to the highest generation to which promotion occurs automatically (the "blocking generation"), but later becomes garbage. The blocking generation is 2 in 32-bit LispWorks and (by default) 3 in 64-bit LispWorks.
You can check which generation individual objects are in (by generation-number), but normally you want to know the total amount of data in various generations. The function room is used for that. In general, it is useful to call
and sometimes also
periodically (every 5 minutes) and log the output. In servers, such logs are essential. From this output you can see how the sizes of the various generations change over time.
If the output shows that the blocking generation grows too much, even though permanant data is not added, you will need to do something about it. In 64-bit LispWorks there is a good chance that you do not have to do anything. In 32-bit LispWorks long-lived processes (for example servers) probably need to do something.
The main thing you will do is calling
. This garbage collects the blocking generation. You should check the state of the memory after calling it by calling room again. If the amount of allocated data (as opposed to total size) did not reduce, you may have a memory leak that causes accumulation of permanent data that does not die.
If gc-generation does free data (that is, the allocation reduces significantly), you probably need to add calls to it to your application.
In 32-bit LispWorks version 5.1 and earlier, the documented way to collect generation 2 is to call
does, plus some additional operations that improve the perfomance of allocation. It also has the advantage that it is the same call that is used in 64-bit LispWorks. We recommend always using gc-generation.
To decide when to call gc-generation, you need to consider the following:
We now discuss these considerations in detail:
(room nil), or programmatically by using the result of room-values. The definition of "excessive growth" depends on the machine that you are running on and what the server actually does. Normally you want to avoid the need for paging, so you should try to keep the size of the image below the size of real memory that it can use. For 32-bit LispWorks on modern machines that have a lot of memory, the limit will be the amount of address space the machine has. In addition, garbage collecting a larger image takes more time. In a typical 32-bit application, 100-200Mb would be the target, though it can be larger. In a 64-bit application the limit is the size of the real memory.
(gc-generation t)can take a significant amount of time. 32-bit LispWorks on a modern machine can collect 100-200Mb in less than a second if it does not page. If it pages, or has a slower CPU, it takes more time. The 64-bit GC is generally faster and better, as long as it does not page, but since you normally deal with much more data in 64-bit images, there may be significant delays in 64-bit LispWorks. If such delays are a problem for your application, you should try to call gc-generation at times when it is less of a problem. Use time to find out how long gc-generation takes in various situations.
In 32-bit LispWorks, by default, generation 2 (which is the "blocking generation") is not collected automatically, because such collection may take a signficant amount of time, so most programmers need to control when it actually happens. You can change this by using collect-generation-2, but usually you need better control, and do a collection of generation 2 when it is appropriate. Therefore if your application generates long-lived data, you need to add calls to gc-generation.
Even if you find that your application does not generate long-lived data (that is, generation 2 does not grow), it is probably a good idea to keep checking, in case some circumstances do cause it to generate long-lived data.
In 64-bit LispWorks by default generation 3 (the "blocking generation") is collected automatically, so there is a good chance that you do not have to do anything. However, you may want to call gc-generation explicitly when you know it is a good time to do it. You may also want to block automatic calls if they they take too long: use set-blocking-gen-num to do that. If generation 3 becomes very big (Gigabytes), you may also consider using marking-gc instead of gc-generation.
Once you set up gc-generation calls, you may still see the image growing even though the allocation does not grow that much. That is normally the result of fragmentation. On 32-bit LispWorks you can use check-fragmentation to check for fragmentation, and try-move-in-generation to prevent it if needed. See Controlling Fragmentation for a discussion.
In 64-bit LispWorks you have a problem with fragmentation only if you use marking-gc. marking-gc has keyword arguments that can be used to reduce fragmentation, and there is a good chance that using these will be enough to avoid serious fragmentation. gc-generation can be used occasionally to eliminate all fragmentation. Check for fragmentation by using gen-num-segments-fragmentation-state.
LispWorks User Guide and Reference Manual - 21 Dec 2011