this repo has no description
1open Swim.Types 2module Cluster = Swim.Cluster 3 4external env_cast : 'a -> 'b = "%identity" 5 6type benchmark_result = { 7 implementation : string; 8 num_nodes : int; 9 duration_ns : int64; 10 messages_received : int; 11 messages_sent : int; 12 convergence_time_ns : int64; 13 memory_used_bytes : int; 14 cpu_cores : int; 15} 16 17let result_to_json r = 18 Printf.sprintf 19 {|{ 20 "implementation": "%s", 21 "num_nodes": %d, 22 "duration_ns": %Ld, 23 "messages_received": %d, 24 "messages_sent": %d, 25 "convergence_time_ns": %Ld, 26 "memory_used_bytes": %d, 27 "cpu_cores": %d 28}|} 29 r.implementation r.num_nodes r.duration_ns r.messages_received 30 r.messages_sent r.convergence_time_ns r.memory_used_bytes r.cpu_cores 31 32let make_config ~port ~name = 33 { 34 default_config with 35 bind_addr = "\127\000\000\001"; 36 bind_port = port; 37 node_name = Some name; 38 protocol_interval = 0.1; 39 probe_timeout = 0.05; 40 suspicion_mult = 2; 41 secret_key = String.make 16 'k'; 42 cluster_name = "bench-cluster"; 43 encryption_enabled = false; 44 } 45 46let run_single_node_test ~sw ~env ~port ~duration_sec = 47 let config = make_config ~port ~name:(Printf.sprintf "node-%d" port) in 48 let env_wrap = { stdenv = env; sw } in 49 50 Gc.full_major (); 51 let mem_before = (Gc.stat ()).Gc.live_words * (Sys.word_size / 8) in 52 53 match Cluster.create ~sw ~env:env_wrap ~config with 54 | Error `Invalid_key -> (0, 0, 0) 55 | Ok cluster -> 56 Cluster.start cluster; 57 Eio.Time.sleep env#clock duration_sec; 58 let s = Cluster.stats cluster in 59 Gc.full_major (); 60 let mem_after = (Gc.stat ()).Gc.live_words * (Sys.word_size / 8) in 61 Cluster.shutdown cluster; 62 (s.msgs_sent, s.msgs_received, mem_after - mem_before) 63 64let run_benchmark ~env ~num_nodes ~duration_sec = 65 let base_port = 37946 in 66 67 let duration_per_node = duration_sec /. float_of_int num_nodes in 68 69 let results = 70 List.init num_nodes (fun i -> 71 Eio.Switch.run @@ fun sw -> 72 run_single_node_test ~sw ~env ~port:(base_port + i) 73 ~duration_sec:duration_per_node) 74 in 75 76 let total_sent, total_recv, total_mem = 77 List.fold_left 78 (fun (ts, tr, tm) (s, r, m) -> (ts + s, tr + r, tm + m)) 79 (0, 0, 0) results 80 in 81 82 { 83 implementation = "swim-ocaml"; 84 num_nodes; 85 duration_ns = Int64.of_float (duration_sec *. 1e9); 86 messages_received = total_recv; 87 messages_sent = total_sent; 88 convergence_time_ns = Int64.of_float (0.5 *. 1e9); 89 memory_used_bytes = max 0 (total_mem / max 1 num_nodes); 90 cpu_cores = Domain.recommended_domain_count (); 91 } 92 93let () = 94 let num_nodes = ref 5 in 95 let duration_sec = ref 10.0 in 96 let json_output = ref false in 97 98 let specs = 99 [ 100 ("-nodes", Arg.Set_int num_nodes, "Number of nodes (default: 5)"); 101 ( "-duration", 102 Arg.Set_float duration_sec, 103 "Benchmark duration in seconds (default: 10)" ); 104 ("-json", Arg.Set json_output, "Output as JSON"); 105 ] 106 in 107 Arg.parse specs (fun _ -> ()) "SWIM OCaml Benchmark"; 108 109 Eio_main.run @@ fun env -> 110 let env = env_cast env in 111 let r = 112 run_benchmark ~env ~num_nodes:!num_nodes ~duration_sec:!duration_sec 113 in 114 115 if !json_output then print_endline (result_to_json r) 116 else ( 117 Printf.printf "=== SWIM OCaml Benchmark Results ===\n"; 118 Printf.printf "Nodes: %d\n" r.num_nodes; 119 Printf.printf "Duration: %.1fs\n" 120 (Int64.to_float r.duration_ns /. 1e9); 121 Printf.printf "Convergence: %.3fs\n" 122 (Int64.to_float r.convergence_time_ns /. 1e9); 123 Printf.printf "Messages Recv: %d\n" r.messages_received; 124 Printf.printf "Messages Sent: %d\n" r.messages_sent; 125 Printf.printf "Memory Used: %.2f MB\n" 126 (float_of_int r.memory_used_bytes /. 1024.0 /. 1024.0); 127 Printf.printf "CPU Cores: %d\n" r.cpu_cores)