Make the GC work harder on low-end hardware instead of calling Gc.compact - #7100
Make the GC work harder on low-end hardware instead of calling Gc.compact#7100kit-ty-kate wants to merge 2 commits into
Conversation
|
Does the problem described above ring a bell? @Octachron @gasche |
|
I can definitely see a performance impact of setting space-overhead through OCAMLRUNPARAM on my own 5.4 or 5.5 switches (below are 5.4 numbers, the results are similar for 5.5): |
|
Maybe more work is done but the space is still allocated? |
|
Indeed, 5.x do not include automatic compaction for now, and in particular they will not release memory to the OS unless compaction is requested explictly. In workloads that suffer from fragmentation this can lead to a noticeable increase of peak memory consumption. (Otherwise this should not change peak memory consumption that much.) It is possible under 4.x that the small overhead setting you put forces automatic compaction much more often, with the result of effectively fighting fragmentation and reducing peak memory usage. I am not familiar with the pacing logic for automatic compaction (most of what I learned about the GC is from 5.x times). |
I'm not sure this is what's happening. I've tried to force manual compaction with trunk with the following trick for good measure and nothing happened either. diff --git a/src/client/opamCliMain.ml b/src/client/opamCliMain.ml
index f921761f6..ea9e6c32e 100644
--- a/src/client/opamCliMain.ml
+++ b/src/client/opamCliMain.ml
@@ -444,6 +444,19 @@ let set_gc_params total_ram =
if total_ram > 0L && (total_ram : int64) < two_GB then begin
log "Low end machine detected. Setting the GC to work harder";
Gc.set {(Gc.get ()) with space_overhead = 20};
+ let _ : Gc.alarm =
+ Gc.create_alarm @@ fun () ->
+ log "Compacting...";
+ Gc.compact ();
+ in
+ let _ : Thread.t =
+ Thread.create (fun () ->
+ while true do
+ Gc.full_major ();
+ done)
+ ()
+ in
+ ()
end
let run () =It feels to me like memory allocation (as in from the system) is completely disconnected from how much the GC is collecting or compacting |
|
I've also tried using ocaml/ocaml#14796 just in case but i get the same behaviour (although the full_major/compact loop is 4x slower than 5.5 for some reason, but it's not finished nor merged so we can ignore that for now) I've also noticed that the full_major/compact loop trick actually uses more system memory than not doing anything (about 250MB more), which seems counter-intuitive |
|
While reading ocaml/ocaml#12193 description, i got to wonder about this:
Does that mean that larger blocks are not compacted? I also debugged this further (see 5420779) and it looks like The logs show: So |
|
Here's a short reproduction case that doesn't use opam lib (but uses its marshalled data): (* ocamlfind ocamlopt -linkpkg -linkall -package unix,threads -thread test.ml *)
(* To test using: cd /tmp && cp ~/.opam/repo/*.cache . && (ulimit -v 400000 && CAMLRUNPARAM=o=20 ./a.out) *)
let get_heap () =
let {Gc.heap_words; _} = Gc.quick_stat () in
heap_words * Sys.word_size / 8 / 1024 / 1024
let () =
Printf.printf "heap1: %d MB\n%!" (get_heap ());
let th =
Thread.create (fun () ->
while true do
Gc.full_major ();
Gc.compact ();
done)
()
in
Printf.printf "heap2: %d MB\n%!" (get_heap ());
let ic = open_in_bin "state-22ED6214.cache" in
Printf.printf "heap3: %d MB\n%!" (get_heap ());
let _ = Marshal.from_channel ic in
Printf.printf "heap4: %d MB\n%!" (get_heap ());
close_in ic;
Printf.printf "heap5: %d MB\n%!" (get_heap ());
Printf.printf "please press Ctrl-C\n%!";
Thread.join thOn 4.14 this uses less than 400MB and on OCaml 5.5 this shoots up to less than 700MB. I'll open a ticket in ocaml/ocaml in a bit. |
Fixes #6521
Tested using
time (ulimit -v <num>000 ; ./opam show --debug --raw dune.3.24.2 > /dev/null)on OCaml 4.14:However testing this code with OCaml 5.x (tested on the latest trunk (ocaml/ocaml#d03f0e4c7), 5.5, 5.4, 5.3, 5.2, 5.1 and 5.0) nothing happens. opam always takes 564MB regardless of
space_overhead. I also tried disabling our useGc.ramp_upjust in case this interfere with this but this doesn't do anything either.