Version française
Home     About     Download     Resources     Contact us    
Browse thread
Global roots causing performance problems
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Markus Mottl <markus.mottl@g...>
Subject: Global roots causing performance problems
Hi,

this is actually a somewhat long-standing issue, but we have only
recently been hit by it in a way that makes working around it hard,
and we would like to know whether there is a reasonable chance that
this could be solved in a future OCaml-release:

Many C-bindings use C-datastructures that refer to OCaml-values.
This, of course, means that these OCaml-values must not be reclaimed
as long as they can still be referred to.  The current OCaml-FFI
already provides functions (caml_register_global_root, etc.) for
protecting such values.  Unfortunately, it seems that this feature was
not implemented with the possibility in mind that one day people might
want to refer to many thousands of OCaml-values (most often closures)
from C-data.  The garbage collector obviously scans all global roots
on every minor collection, which leads to a very substantial
performance loss in such situations.  The minor heap may often even be
almost empty, i.e. we might only need to chase a few live values,
while we would still have to scan through thousands of global roots.

A common and unfortunately quite clumsy trick to work around this
limitation is to use a hash table from integers to the values to be
protected.  Instead of storing the OCaml-value itself in the
C-datastructure and protecting it, we only need to store the integer
handle for the value, which does not need to be protected.  C-land
then only needs to perform a callback into OCaml-land with the integer
handle in order to use the value it refers to, or to remove it it from
the hash table if it isn't needed anymore.

The problem here is that this only makes sense when writing a new
library or when modifying a small existing one.  We have run into this
issue with LablGTK, which is just way too large and complex to make
this a feasible thing to do.

We therefore wonder whether it wouldn't be much more effective to fix
the runtime.  I don't know the exact details of how things currently
work, but I guess that it would be possible to have two separate sets
of global roots for the minor and major heap.  Then, once a value gets
oldified, the global root, too, could wander to the corresponding set.
 The set for the major heap could then be scanned only once per full
major cycle, maybe even in slices, too.  Would this suggestion be easy
to implement?

Best regards,
Markus

-- 
Markus Mottl        http://www.ocaml.info        markus.mottl@gmail.com