Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.Sign up
minor_words in gc stats sometimes double counts allocations #7798
Original bug ID: 7798
The symptom is simple: sometimes you allocate n words and the gc stats increase by 2n.
Here is a program that shows this behavior :
This has been causing some very hard to understand spurious failures in allocation tests where the reported allocation is too high by a few words, despite measuring allocation like so (no signals/ocaml finalizers in this context):
let minor_words_allocated f =
This is because if you're unlucky and the call to Gc.minor finishes the major cycle, the major gc goes into Phase_idle and call caml_request_minor_gc (). Which causes the next minor allocation to trigger a minor gc and be double counted because of the bug above.
The double counting does not happen all the time. caml_alloc is correct. The inline assembly is wrong. The assembly functions used with -compact are also wrong.
After having spent hours figuring out what the problem is, the workaround is easy enough: do one allocation after Gc.minor () to set off the requested minor gc, if any.
So I'd like to ask for the stats to be fixed (and the documentation to be updated, unless it's referring to something else).
The fix doesn't seem too hard: before calling caml_call_gc, undo the subtraction to the minor heap frontier. In the non inlined-assembly, I think this is not contentious. In the inlined assembly, code size might be a concern? But even that seems fixable (shouldn't matter for big allocations, and for small allocations, one can use a family of caml_call_gc_X functions that change back the heap frontier by X bytes and jump to caml_call_gc).
let rec zero_alloc_bytes_of_int buf n i =
let zero_alloc_string_of_int buf n =
let () =
let () =
Comment author: @stedolan
We ran into this bug on the multicore branch a while ago, where it caused crashes since we assume that the minor heap does not have holes in it. I didn't realise that this affected trunk as well! The fix is as you say (see commit 8ceec49 on github.com/ocamllabs/ocaml-multicore).
By the way, Alloc_small in caml/memory.h (used for allocations in the bytecode interpreter) already undoes the subtraction before entering the GC, which is why this bug only affects native code.