Created
January 22, 2026 00:38
-
-
Save tmcgilchrist/1252ecf7671ec8d3bf5169207babc80e to your computer and use it in GitHub Desktop.
Simple weak array benchmark that mirrors original hugebench structure. Used for testing Transparent Huge Pages and OCaml GC compaction.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (* Simple weak array benchmark that mirrors original hugebench structure *) | |
| let enable_hugepages () = | |
| let ch = open_in "/proc/self/maps" in | |
| let module Syscall = struct | |
| external madvise : (int64[@unboxed]) -> (int64[@unboxed]) -> (int[@untagged]) -> (int[@untagged]) = | |
| "unimplemented" "madvise" | |
| end in | |
| try | |
| while true do | |
| Scanf.sscanf (input_line ch) "%Lx-%Lx %s %Lx %x:%x %Ld %s" | |
| (fun start_addr end_addr perms offset devmaj devmin inode path -> | |
| let len = Int64.sub end_addr start_addr in | |
| if perms = "rw-p" && inode = 0L && path <> "[heap]" && path <> "[stack]" && len >= 0x200000L then | |
| ignore (Syscall.madvise start_addr len 25)) | |
| done | |
| with End_of_file -> close_in ch | |
| type t = { | |
| n : int; | |
| mutable opt : int option | |
| } | |
| (* Benchmark accessing through weak array *) | |
| let bench weak_arr = | |
| let before = Sys.time () in | |
| let iters = 50_000 in | |
| for i = 1 to iters do | |
| let sum = ref 0 in | |
| for n = 0 to Weak.length weak_arr - 1 do | |
| match Weak.get weak_arr n with | |
| | Some obj -> sum := !sum + obj.n | |
| | None -> () (* Shouldn't happen in this benchmark *) | |
| done; | |
| ignore (Sys.opaque_identity !sum); | |
| done; | |
| let after = Sys.time () in | |
| Printf.printf " %.3f s (%.1f ns/elem)\n%!" | |
| (after -. before) | |
| (1e9 *. ((after -. before) /. float_of_int (iters * Weak.length weak_arr))) | |
| let () = | |
| (* Create objects - same as original hugebench *) | |
| let opts = Array.init 10_000_000 (fun n -> {n; opt=Some n}) in | |
| (* Create weak array holding subset of objects *) | |
| let weak_subset = Weak.create 10_000 in | |
| for i = 0 to 9_999 do | |
| Weak.set weak_subset i (Some opts.(i * 1000)) | |
| done; | |
| Gc.minor (); | |
| Printf.printf "After initialisation and minor GC:\n%!"; | |
| for _ = 1 to 3 do bench weak_subset done; | |
| enable_hugepages (); | |
| Printf.printf "After MADV_COLLAPSE to enable hugepages:\n%!"; | |
| for _ = 1 to 3 do bench weak_subset done; | |
| (* Clear the options, making space in the size-1 pool for compaction *) | |
| opts |> Array.iter (fun t -> t.opt <- None); | |
| Gc.compact (); | |
| Printf.printf "After compaction:\n%!"; | |
| for _ = 1 to 3 do bench weak_subset done; | |
| ignore (Sys.opaque_identity (opts, weak_subset)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment