Skip to content

forced_major and compactions are always 0 unless the main domain makes the call #115

Description

@tmcgilchrist

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions