Skip to content

Commit 9ec8d13

Browse files
committed
perf: relax OCaml 5.x GC pacing for custom blocks, warn on 5.0–5.3
EasyCrypt hash-conses its AST and allocates zarith/GMP custom blocks heavily. On OCaml 5.x the default custom_major_ratio paces the major GC far too aggressively over that external memory (OCaml issue #14533, pronounced on 5.5), costing large amounts of CPU for no memory benefit: compiling a large file (NTTAlgebra.ec) measured ~5x slower than on 4.14 (1255s vs 339s), with the same ~1GB working set. Set custom_major_ratio to 250 on OCaml >= 5, which restores 4.14-class performance (5.5: 1255s -> 233s). This is a no-op on 5.4, whose default pacing is already fine, and harmless there. Additionally, warn at startup on OCaml 5.0–5.3, whose minor GC over-promotes values reachable from ephemeron/weak-table keys (OCaml issue #13643), causing severe memory blowup with EasyCrypt's weak-table hash-consing. Fixed upstream in OCaml 5.4; recommend upgrading.
1 parent 0096d84 commit 9ec8d13

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

src/ec.ml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,36 @@ open EcOptions
66
module EP = EcParsetree
77
module T = EcTerminal
88

9+
(* -------------------------------------------------------------------- *)
10+
(* OCaml runtime version as (major, minor), parsed from [Sys.ocaml_version]. *)
11+
let ocaml_version : int * int =
12+
try Scanf.sscanf Sys.ocaml_version "%d.%d" (fun a b -> (a, b))
13+
with _ -> (0, 0)
14+
15+
(* EasyCrypt hash-conses its AST and leans heavily on zarith/GMP custom blocks.
16+
On OCaml 5.x the default [custom_major_ratio] paces the major GC far too
17+
aggressively over that external memory (OCaml issue #14533, pronounced on
18+
5.5), which costs a large amount of CPU for no memory benefit. Relaxing the
19+
ratio restores 4.14-class performance. *)
20+
let tune_gc () =
21+
if fst ocaml_version >= 5 then
22+
Gc.set { (Gc.get ()) with Gc.custom_major_ratio = 250 }
23+
24+
(* OCaml 5.0-5.3's minor GC over-promotes values reachable from ephemeron /
25+
weak-table keys (OCaml issue #13643), causing severe memory blowup with
26+
EasyCrypt's weak-table hash-consing. Fixed in OCaml 5.4. *)
27+
let warn_ocaml_version (terminal : T.terminal) =
28+
match ocaml_version with
29+
| (5, minor) when minor <= 3 ->
30+
T.notice ~immediate:true `Warning
31+
(Printf.sprintf
32+
"running on OCaml %s: OCaml 5.0-5.3 have a garbage-collector \
33+
regression (OCaml issue #13643) that can cause severe memory blowup \
34+
in EasyCrypt; please upgrade to OCaml >= 5.4"
35+
Sys.ocaml_version)
36+
terminal
37+
| _ -> ()
38+
939
(* -------------------------------------------------------------------- *)
1040
let copyright =
1141
let sentences =
@@ -117,6 +147,10 @@ let print_config config =
117147

118148
(* -------------------------------------------------------------------- *)
119149
let main () =
150+
(* On OCaml 5.x, relax the major-GC pacing over zarith/GMP custom blocks
151+
(see [tune_gc]). *)
152+
tune_gc ();
153+
120154
(* When started from Emacs28 on Apple M1, the set of blocks signals *
121155
* disallows Why3 server to detect external provers completion *)
122156
let _ : int list = Unix.sigprocmask Unix.SIG_SETMASK [] in
@@ -708,6 +742,9 @@ let main () =
708742
if T.interactive terminal then
709743
T.notice ~immediate:true `Warning copyright terminal;
710744

745+
(* Warn about GC-regressed OCaml versions (5.0-5.3) *)
746+
warn_ocaml_version terminal;
747+
711748
(* Check if a location is past the -upto point *)
712749
let past_upto (loc : EcLocation.t) =
713750
match state.upto with

0 commit comments

Comments
 (0)