Next: Garbage collection
Up: Memory Organisation And Garbage
Previous: Memory Organisation And Garbage
  Index
Subsections
This chapter may be skipped on a first reading.
Its purpose is to give the advanced user a better understanding
of how the system uses memory resources.
In a high level language like Prolog it is often not obvious for the programmer
to see where the system allocates or frees memory.
The sizes of the different memory areas can be queried by means of the predicate
statistics/2 and statistics/0 prints a summary of all these data.
Here is a sample output:
[eclipse 1]: statistics.
times: [0.133333, 0.65, 304.809] seconds
global_stack_used: 724 bytes
global_stack_allocated: 102400 bytes
global_stack_peak: 1576960 bytes
trail_stack_used: 32 bytes
trail_stack_allocated: 16384 bytes
trail_stack_peak: 16384 bytes
control_stack_used: 392 bytes
control_stack_allocated:4096 bytes
control_stack_peak: 4096 bytes
local_stack_used: 288 bytes
local_stack_allocated: 4096 bytes
local_stack_peak: 4096 bytes
code_heap_allocated: 326888 bytes
code_heap_used: 326888 bytes
general_heap_allocated: 291608 bytes
general_heap_used: 278432 bytes
gc_number: 0
gc_collected: 0 bytes
gc_area: 0 bytes
gc_ratio: 100.0 %
gc_time: 0.0 seconds
dictionary_entries: 2494
dict_hash_usage: 1498 / 8191
dict_hash_collisions: 155 / 1498
dict_gc_number: 0
dict_gc_time: 0.0 seconds
The used-figures indicate the actual usage at the moment the
statistics built-in was called. The allocated value is the
amount of memory that is reserved for this area and actually occupied
by the ECLiPSe process. The peak value indicates what was the
maximum allocated amount during the session.
In the following we will discuss the six memory areas mentioned.
The gc-figures are described in section 19.2.
The Code Heap
The code heap is used to store compiled Prolog code and external predicates.
Consequently its size is increased by the various compile-predicates,
the assert-family and by load/1.
Space on the code heap is freed when single clauses (retract) or
whole predicates (abolish) are removed from the system.
Note that space reclaiming is usually delayed in these cases, since the
removed code may still be under execution.
Erasing a module also reclaims all the memory occupied by the module's
predicates.
The General Heap
The general heap is used to store a variety of data:
- internal database:
Term that are recorded using the record-family
of builtins are stored on the general heap. The space is freed when the
terms are erased.
- arrays and global variables:
Space for storing global variables and arrays (make_array, setval)
is allocated from the general heap.
When a global variable is overwritten , the space for the old value
is reclaimed. All memory related to a global variable or array is
reclaimed when it is destroyed using erase_array/1.
- dictionary:
The dictionary is the system's table of atoms and functors.
The dictionary grows whenever the system encounters an atom or functor that
has not been mentioned so far.
The dictionary shrinks on dictionary garbage collections, which are triggered
automatically after a certain number of new entries has been made.
The dictionary is designed to hold several thousands of entries,
the current number of entries can be queried with statistics/0,2.
- various descriptors:
The system manages a number of other internal tables (for modules, predicates,
streams, operators, etc.) that are also allocated on the general heap.
This space is reclaimed when the related Prolog objects cease to exist.
- I/O-buffers:
When streams are opened, the system allocates buffers from the
general heap. They are freed when the stream is closed.
- allocation in C-externals:
If external predicates written in C call malloc() or related C library
functions, this space is also allocated from the general heap.
It is the user's responsibility to free this space if it becomes unused.
The Local Stack
The Local Stack is very similar to the call/return stack in procedural
languages.
It holds Prolog variables and return addresses.
Space on this stack is allocated during execution of a clause and deallocated
before the last subgoal is called (due to tail recursion / last call
optimisation).
This deallocation can not be done when the clause exits nondeterministically
(this can be checked with the debugger or the profiling facility).
However, if a deallocation has been delayed due to nondeterminism, it is
finally done when a cut is executed or when execution fails beyond
the allocation point.
Hence the ways to limit growth of the local stack are
- use tail recursion where possible
- avoid unnecessary nondeterminism (cf. 19.1.4)
The Control Stack
The main use of the Control Stack is to store so-called choicepoints.
A choicepoint is a description of the system's state at a certain point
in execution.
It is created when more than one clause of a predicate apply to a given goal.
Should the first clause fail, the system will backtrack
to the place where the choice was made, the old state will be restored
from the choicepoint and the next clause will be tried.
Disjunctions (;/2) also create choicepoints.
The only way to reduce Control Stack usage is to avoid unnecessary
nondeterminism.
This is done by writing deterministic predicates in such a way that they
can be recognised by the system.
The debugger can help to identify nondeterministic predicates:
When it displays an *EXIT port instead of EXIT then the predicate
has left a choicepoint behind.
In this case it should be checked whether the nondeterminism was intended.
If not, the predicate can often be made deterministic by
- writing the clause heads such that a matching clause can be more
easily selected by indexing
- using the if-then-else construct (.. -> .. ; ..)
- deliberate insertion of (green) cuts
The Global Stack
The Global Stack holds Prolog structures, lists, strings and long numbers.
So the user's selection of data structures is largely responsible
for the growth of this stack (cf. 6.4).
In coroutining mode, delayed goals also consume space on the Global Stack.
It also stores source variable names for terms which
were read in with the flag variable_names being on.
When this feature is not needed, it should be turned off
so that space on the global stack is saved.
The global stack grows while a program creates data structures.
It is popped only on failure. ECLiPSe therefore provides a garbage collector
for the Global Stack which is called when a certain amount
of new space has been consumed. See section 19.2 for how this process
can be controlled.
Note again that unnecessary nondeterminism reduces the amount of garbage
that can be reclaimed and should therefore be avoided.
The Trail Stack
The Trail Stack is used to record information that is needed on backtracking.
It is therefore closely related to the Control Stack.
Ways to reduce Trail Stack consumption are
- avoid unnecessary nondeterminism
- supply mode declarations
The Trail Stack is popped on failure and
is garbage collected together with the Global Stack.
Next: Garbage collection
Up: Memory Organisation And Garbage
Previous: Memory Organisation And Garbage
  Index
1999-08-06