[Gc] Understanding the performance of a `libgc'-based application
ludovic.courtes at laas.fr
Mon Nov 27 01:25:37 PST 2006
I started porting the Guile interpreter to `libgc' some time ago. The
port is now complete feature-wise, but it is almost twice as slow as the
original Guile (e.g., when running `GCBench.scheme'). I investigated
various tweaks without much success so far. So I'm looking for feedback
to see if I'm missing some obvious optimization opportunity, or at least
to understand those performance characteristics.
In Guile, all objects are implemented as a cell (two words) or double
cell (four words) which may contain pointers to additional data (e.g.,
string buffers, bignums, etc.). With the current GC, cells are
allocated from the "cell heap" while other data (string buffers, etc.)
are allocated using libc's `malloc ()'. Guile's GC uses a mark and
sweep algorithm. It scans the stack and the cell heap for live
pointers. During the mark phase, the GC also invokes the various
type-specific mark procedures. When an unmarked cell is encountered
during the sweep phase, it marks it as free and calls `free ()' or a
type-specific finalizer on its associated data, if need be.
In the `libgc'-based Guile, `malloc ()' is no longer used. Instead, all
data is allocated using either `GC_MALLOC_ATOMIC ()' or `GC_MALLOC ()'
(the former is used for string buffers and file contents). Thus, Guile
code no longer needs to provide custom mark/free procedures.
Furthermore, "all interior pointers" is turned off and the few valid
displacements are registered.
Guile uses weak hash tables extensively and those are implemented as
disappearing links in the `libgc'-based Guile[*]. Running Guile up to
the prompt with `GC_DUMP_REGULARLY' shows that it uses around 5000
disappearing links. Is this a likely source of performance loss?
I would appreciate comments and suggestions.
[*] Speaking of this, I support Laurynas Biveinis's proposal to allow
for values other than NULL (see
More information about the Gc