gc-stats guards all four collection counters with ring_id == 0 (olly_gc_stats.5.3.ml:266-282). That is correct for two of them and wrong for the other two, because the phases have different semantics.
EV_MINOR and EV_MAJOR_GC_STW mark global stop-the-world points, so every live domain emits them once per cycle. Counting a single domain index yields the cycle count rather than a per-domain sum, and index 0 is the right one to count because the main domain outlives the others.
EV_EXPLICIT_GC_COMPACT, EV_EXPLICIT_GC_MAJOR and EV_EXPLICIT_GC_FULL_MAJOR are different. They are spans around a user API call, Gc.compact, Gc.major and Gc.full_major, and are emitted only on the domain that made the call. The ring_id == 0 guard discards all of them unless that domain happens to be the main one.
Same program, same five Gc.full_major () and five Gc.compact (), differing only in which domain calls them:
let work () =
for _ = 1 to 5 do
let acc = ref [] in
for i = 1 to 50_000 do acc := (Array.make 8 i) :: !acc done;
ignore (Sys.opaque_identity !acc);
Gc.full_major ();
Gc.compact ()
done
(* main domain calls *) let () = work ()
(* worker domain calls *) let () = Domain.join (Domain.spawn work)
### explicit GC called by MAIN domain
Major Gen: 40 collections 5 forced collections
Compactions: 5
### explicit GC called by WORKER domain
Major Gen: 11 collections 0 forced collections
Compactions: 0
The fix should be dropping && ring_id == 0 for the three EV_EXPLICIT_GC_* phases and keep it for EV_MINOR and EV_MAJOR_GC_STW.
gc-statsguards all four collection counters withring_id == 0(olly_gc_stats.5.3.ml:266-282). That is correct for two of them and wrong for the other two, because the phases have different semantics.EV_MINORandEV_MAJOR_GC_STWmark global stop-the-world points, so every live domain emits them once per cycle. Counting a single domain index yields the cycle count rather than a per-domain sum, and index 0 is the right one to count because the main domain outlives the others.EV_EXPLICIT_GC_COMPACT,EV_EXPLICIT_GC_MAJORandEV_EXPLICIT_GC_FULL_MAJORare different. They are spans around a user API call,Gc.compact,Gc.majorandGc.full_major, and are emitted only on the domain that made the call. Thering_id == 0guard discards all of them unless that domain happens to be the main one.Same program, same five
Gc.full_major ()and fiveGc.compact (), differing only in which domain calls them:The fix should be dropping
&& ring_id == 0for the threeEV_EXPLICIT_GC_*phases and keep it forEV_MINORandEV_MAJOR_GC_STW.