type alloc_stats = { minor_words : float; major_words : float; minor_collections : int; major_collections : int; heap_words : int; live_words : int; } let get_stats () = Gc.full_major (); let stat = Gc.stat () in { minor_words = stat.minor_words; major_words = stat.major_words; minor_collections = stat.minor_collections; major_collections = stat.major_collections; heap_words = stat.heap_words; live_words = stat.live_words; } let diff_stats before after = { minor_words = after.minor_words -. before.minor_words; major_words = after.major_words -. before.major_words; minor_collections = after.minor_collections - before.minor_collections; major_collections = after.major_collections - before.major_collections; heap_words = after.heap_words - before.heap_words; live_words = after.live_words - before.live_words; } let print_stats label stats = Printf.printf "=== %s ===\n" label; Printf.printf " Minor words: %.0f (%.2f KB)\n" stats.minor_words (stats.minor_words *. 8.0 /. 1024.0); Printf.printf " Major words: %.0f (%.2f KB)\n" stats.major_words (stats.major_words *. 8.0 /. 1024.0); Printf.printf " Minor GCs: %d\n" stats.minor_collections; Printf.printf " Major GCs: %d\n" stats.major_collections; Printf.printf " Heap words: %d (%.2f KB)\n" stats.heap_words (float_of_int stats.heap_words *. 8.0 /. 1024.0); Printf.printf " Live words: %d (%.2f KB)\n" stats.live_words (float_of_int stats.live_words *. 8.0 /. 1024.0); Printf.printf "\n" type bench_result = { name : string; iterations : int; total_time_ms : float; per_op_time_us : float; allocs : alloc_stats; allocs_per_op : float; } let print_bench_result r = Printf.printf "%-30s | %6d iters | %8.2f ms | %8.2f µs/op | %10.0f words/op\n" r.name r.iterations r.total_time_ms r.per_op_time_us r.allocs_per_op let bench name ~iterations f = Gc.full_major (); Gc.compact (); let before = get_stats () in let t0 = Unix.gettimeofday () in for _ = 1 to iterations do ignore (f ()) done; let t1 = Unix.gettimeofday () in let after = get_stats () in let allocs = diff_stats before after in let total_time_ms = (t1 -. t0) *. 1000.0 in let per_op_time_us = total_time_ms *. 1000.0 /. float_of_int iterations in let allocs_per_op = allocs.minor_words /. float_of_int iterations in { name; iterations; total_time_ms; per_op_time_us; allocs; allocs_per_op } let leak_check name ~rounds ~ops_per_round f = Printf.printf "\n=== Leak Check: %s ===\n" name; Printf.printf "Running %d rounds of %d operations each...\n\n" rounds ops_per_round; let heap_sizes = Array.make rounds 0 in let live_sizes = Array.make rounds 0 in for round = 0 to rounds - 1 do for _ = 1 to ops_per_round do ignore (f ()) done; Gc.full_major (); Gc.compact (); let stat = Gc.stat () in heap_sizes.(round) <- stat.heap_words; live_sizes.(round) <- stat.live_words; if round mod 10 = 0 || round = rounds - 1 then Printf.printf " Round %3d: heap=%d words, live=%d words\n" (round + 1) stat.heap_words stat.live_words done; let first_heap = heap_sizes.(0) in let last_heap = heap_sizes.(rounds - 1) in let first_live = live_sizes.(0) in let last_live = live_sizes.(rounds - 1) in let heap_growth = last_heap - first_heap in let live_growth = last_live - first_live in Printf.printf "\nResults:\n"; Printf.printf " Heap growth: %d words (%.2f KB)\n" heap_growth (float_of_int heap_growth *. 8.0 /. 1024.0); Printf.printf " Live growth: %d words (%.2f KB)\n" live_growth (float_of_int live_growth *. 8.0 /. 1024.0); if live_growth > 1000 then Printf.printf " ⚠️ POTENTIAL LEAK: Live memory grew by %d words\n" live_growth else Printf.printf " ✓ No significant memory leak detected\n"; (heap_growth, live_growth) let run_benchmarks name benchmarks = Printf.printf "\n"; Printf.printf "╔═══════════════════════════════════════════════════════════════════════════════╗\n"; Printf.printf "║ %-77s ║\n" (Printf.sprintf "BENCHMARK: %s" name); Printf.printf "╠═══════════════════════════════════════════════════════════════════════════════╣\n"; Printf.printf "║ %-30s | %6s | %8s | %11s | %14s ║\n" "Operation" "Iters" "Total" "Per Op" "Allocs/Op"; Printf.printf "╠═══════════════════════════════════════════════════════════════════════════════╣\n"; List.iter (fun r -> Printf.printf "║ %-30s | %6d | %6.1f ms | %8.2f µs | %11.0f w ║\n" r.name r.iterations r.total_time_ms r.per_op_time_us r.allocs_per_op) benchmarks; Printf.printf "╚═══════════════════════════════════════════════════════════════════════════════╝\n"