Previous Up

19.2  Garbage collection

The four stacks grow an shrink as needed.1 In addition, ECLiPSe provides an incremental garbage collector for the global and the trail stack. It is also equipped with a dictionary garbage collector that frees memory that is occupied by obsolete atoms and functors. Both collectors are switched on by default and are automatically invoked from time to time. Nevertheless, there are some predicates to control their action. The following predicate calls affect both collectors:

set_flag(gc, on):
Enable the garbage collector (the default).
set_flag(gc, verbose):
The same as ’on’, but print a message on every collection (the message goes to toplevel_output):
GC ... global: 96208 - 88504 (92.0 %), trail: 500 - 476 (95.2 %), time: 0.017
It displays the area to be searched for garbage, the amount and percentage of garbage, and the time for the collection. The message of the dictionary collector is as follows:
DICTIONARY GC ... 2814 - 653, (23.2 %), time: 0.033
It displays the number of dictionary entries before the collection, the number of collected entries, the percentage of reduction and the collection time.
set_flag(gc, off):
Disable the garbage collector (and risk an overflow), e.g., for time-critical execution sequences.

Predicate calls related to the stack collector are:

set_flag(gc_policy, adaptive):
This option affects the triggering heuristics of the garbage collector, together with the gc_interval setting. The adaptive policy (the default) minimises garbage collection time.
set_flag(gc_policy, fixed):
As above, but the fixed policy minimises space consumption.
set_flag(gc_interval, Nbytes):
Specify how often the collector is to be invoked. Roughly, Nbytes is the number of bytes that your program can use up before a garbage collection is triggered. There may be programs that create lots of (useful) lists and structures while leaving few garbage. This will cause the garbage collector to run frequently while reclaiming little space. If you suspect this, you should call statistics/0 and check the garbage ratio. If it is very low (say below 50%) it may make sense to increase the gc_interval, thus reducing the number of garbage collections. This is normally only necessary when the gc_policy is set to fixed. With gc_policy set to adaptive, the collection intervals will be adjusted automatically.
Request an immediate collection (only if enabled). The use of this predicate should be restricted to situations where the automatic triggering performs badly. It should then be inserted in a place where you know for sure that you have just created a lot of garbage, e.g., before the tail-recursive call in something like
cycle(OldState) :-
        transform(OldState, NewState),  /* long computation     */
        garbage_collect,                /* OldState is obsolete */
statistics(gc_number, N):
The number of stack garbage collections performed during this ECLiPSe session.
statistics(gc_collected, Bytes):
The amount of global stack space (in bytes) reclaimed by all the garbage collections.
statistics(gc_area, Bytes):
The average global stack area that was scanned by each garbage collection. This number should be close to the amount selected with gc_interval, if it is much larger, gc_interval should be increased.
statistics(gc_ratio, Percentage):
The average percentage of garbage found and reclaimed by each garbage collection. If this ratio is low, gc_interval should be increased.
statistics(gc_time, Seconds):
The total cpu time spent during all garbage collections.

Predicates related to the dictionary collector are:

set_flag(gc_interval_dict, N):
Specify that the dictionary collector should be invoked after N new dictionary entries have been made.
statistics(dict_gc_number, N):
The number of garbage collections performed on the dictionary during this ECLiPSe session.
statistics(dict_gc_time, Seconds):
The total cpu time spent by all dictionary garbage collections.

Provided that the underlying operating system supports this.

Previous Up