this repo has no description
1open Swim.Types
2module Cluster = Swim.Cluster
3
4external env_cast : 'a -> 'b = "%identity"
5
6type node_result = {
7 port : int;
8 messages_sent : int;
9 messages_received : int;
10 members_seen : int;
11 memory_bytes : int;
12 elapsed_sec : float;
13}
14
15let result_to_json r =
16 Printf.sprintf
17 {|{"port":%d,"messages_sent":%d,"messages_received":%d,"members_seen":%d,"memory_bytes":%d,"elapsed_sec":%.3f}|}
18 r.port r.messages_sent r.messages_received r.members_seen r.memory_bytes
19 r.elapsed_sec
20
21let make_config ~port ~name =
22 {
23 default_config with
24 bind_addr = "\127\000\000\001";
25 bind_port = port;
26 node_name = Some name;
27 protocol_interval = 0.2;
28 probe_timeout = 0.1;
29 suspicion_mult = 2;
30 secret_key = String.make 16 'k';
31 cluster_name = "";
32 encryption_enabled = false;
33 }
34
35let run_node ~env ~port ~peers ~duration_sec =
36 Gc.full_major ();
37 let mem_before = (Gc.stat ()).Gc.live_words * (Sys.word_size / 8) in
38 let start_time = Unix.gettimeofday () in
39
40 Eio.Switch.run @@ fun sw ->
41 let config = make_config ~port ~name:(Printf.sprintf "node-%d" port) in
42 let env_wrap = { stdenv = env; sw } in
43
44 match Cluster.create ~sw ~env:env_wrap ~config with
45 | Error `Invalid_key -> Unix._exit 1
46 | Ok cluster ->
47 Cluster.start cluster;
48
49 List.iter
50 (fun peer_port ->
51 if peer_port <> port then
52 let peer_id =
53 node_id_of_string (Printf.sprintf "node-%d" peer_port)
54 in
55 let peer_addr =
56 `Udp (Eio.Net.Ipaddr.of_raw "\127\000\000\001", peer_port)
57 in
58 let peer = make_node_info ~id:peer_id ~addr:peer_addr ~meta:"" in
59 Cluster.add_member cluster peer)
60 peers;
61
62 Eio.Time.sleep env#clock duration_sec;
63
64 let s = Cluster.stats cluster in
65 let members = Cluster.members cluster in
66
67 Gc.full_major ();
68 let mem_after = (Gc.stat ()).Gc.live_words * (Sys.word_size / 8) in
69 let elapsed = Unix.gettimeofday () -. start_time in
70
71 let result =
72 {
73 port;
74 messages_sent = s.msgs_sent;
75 messages_received = s.msgs_received;
76 members_seen = List.length members;
77 memory_bytes = max 0 (mem_after - mem_before);
78 elapsed_sec = elapsed;
79 }
80 in
81
82 print_endline (result_to_json result);
83 flush stdout;
84 Unix._exit 0
85
86let parse_peers s =
87 String.split_on_char ',' s
88 |> List.filter (fun s -> String.length s > 0)
89 |> List.map int_of_string
90
91let () =
92 let port = ref 0 in
93 let peers_str = ref "" in
94 let duration_sec = ref 10.0 in
95
96 let specs =
97 [
98 ("-port", Arg.Set_int port, "Port to bind to (required)");
99 ("-peers", Arg.Set_string peers_str, "Comma-separated peer ports");
100 ("-duration", Arg.Set_float duration_sec, "Duration in seconds");
101 ]
102 in
103 Arg.parse specs (fun _ -> ()) "SWIM Single Node Benchmark";
104
105 if !port = 0 then (
106 Printf.eprintf "Error: -port is required\n";
107 exit 1);
108
109 let peers = parse_peers !peers_str in
110
111 Eio_main.run @@ fun env ->
112 let env = env_cast env in
113 run_node ~env ~port:!port ~peers ~duration_sec:!duration_sec