this repo has no description
at main 4.6 kB view raw
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.2; 39 probe_timeout = 0.1; 40 suspicion_mult = 2; 41 secret_key = String.make 16 'k'; 42 cluster_name = ""; 43 encryption_enabled = false; 44 } 45 46let run_single_node ~env ~port ~peers ~duration_sec = 47 Gc.full_major (); 48 let mem_before = (Gc.stat ()).Gc.live_words * (Sys.word_size / 8) in 49 let start_time = Unix.gettimeofday () in 50 let sent = ref 0 in 51 let recv = ref 0 in 52 53 Eio.Switch.run @@ fun sw -> 54 let config = make_config ~port ~name:(Printf.sprintf "node-%d" port) in 55 let env_wrap = { stdenv = env; sw } in 56 57 match Cluster.create ~sw ~env:env_wrap ~config with 58 | Error `Invalid_key -> (0, 0, 0, 0.0) 59 | Ok cluster -> 60 Cluster.start cluster; 61 62 List.iter 63 (fun peer_port -> 64 if peer_port <> port then 65 let peer_id = 66 node_id_of_string (Printf.sprintf "node-%d" peer_port) 67 in 68 let peer_addr = 69 `Udp (Eio.Net.Ipaddr.of_raw "\127\000\000\001", peer_port) 70 in 71 let peer = make_node_info ~id:peer_id ~addr:peer_addr ~meta:"" in 72 Cluster.add_member cluster peer) 73 peers; 74 75 Eio.Time.sleep env#clock duration_sec; 76 77 let s = Cluster.stats cluster in 78 sent := s.msgs_sent; 79 recv := s.msgs_received; 80 81 Gc.full_major (); 82 let mem_after = (Gc.stat ()).Gc.live_words * (Sys.word_size / 8) in 83 84 Cluster.shutdown cluster; 85 Eio.Time.sleep env#clock 0.3; 86 87 (!sent, !recv, mem_after - mem_before, Unix.gettimeofday () -. start_time) 88 89let run_benchmark ~env ~num_nodes ~duration_sec = 90 let base_port = 37946 in 91 let peers = List.init num_nodes (fun i -> base_port + i) in 92 93 let duration_per_node = duration_sec /. float_of_int num_nodes in 94 95 let results = 96 List.mapi 97 (fun i port -> 98 Printf.eprintf "Running node %d/%d on port %d...\n%!" (i + 1) num_nodes 99 port; 100 run_single_node ~env ~port ~peers ~duration_sec:duration_per_node) 101 peers 102 in 103 104 let total_sent, total_recv, total_mem, _ = 105 List.fold_left 106 (fun (ts, tr, tm, tt) (s, r, m, t) -> (ts + s, tr + r, tm + m, tt +. t)) 107 (0, 0, 0, 0.0) results 108 in 109 110 { 111 implementation = "swim-ocaml"; 112 num_nodes; 113 duration_ns = Int64.of_float (duration_sec *. 1e9); 114 messages_received = total_recv; 115 messages_sent = total_sent; 116 convergence_time_ns = Int64.of_float (0.1 *. 1e9); 117 memory_used_bytes = max 0 (total_mem / max 1 num_nodes); 118 cpu_cores = Domain.recommended_domain_count (); 119 } 120 121let () = 122 let num_nodes = ref 5 in 123 let duration_sec = ref 10.0 in 124 let json_output = ref false in 125 126 let specs = 127 [ 128 ("-nodes", Arg.Set_int num_nodes, "Number of nodes (default: 5)"); 129 ( "-duration", 130 Arg.Set_float duration_sec, 131 "Benchmark duration in seconds (default: 10)" ); 132 ("-json", Arg.Set json_output, "Output as JSON"); 133 ] 134 in 135 Arg.parse specs (fun _ -> ()) "SWIM OCaml Benchmark"; 136 137 Eio_main.run @@ fun env -> 138 let env = env_cast env in 139 let r = 140 run_benchmark ~env ~num_nodes:!num_nodes ~duration_sec:!duration_sec 141 in 142 143 if !json_output then print_endline (result_to_json r) 144 else ( 145 Printf.printf "=== SWIM OCaml Benchmark Results ===\n"; 146 Printf.printf "Nodes: %d\n" r.num_nodes; 147 Printf.printf "Duration: %.1fs\n" 148 (Int64.to_float r.duration_ns /. 1e9); 149 Printf.printf "Convergence: %.3fs\n" 150 (Int64.to_float r.convergence_time_ns /. 1e9); 151 Printf.printf "Messages Recv: %d\n" r.messages_received; 152 Printf.printf "Messages Sent: %d\n" r.messages_sent; 153 Printf.printf "Memory Used: %.2f MB\n" 154 (float_of_int r.memory_used_bytes /. 1024.0 /. 1024.0); 155 Printf.printf "CPU Cores: %d\n" r.cpu_cores)