this repo has no description
1#!/bin/bash
2#
3# SWIM OCaml Parallel Benchmark Coordinator
4# Spawns N nodes in parallel, collects JSON results, aggregates stats
5#
6
7set -e
8
9NUM_NODES=${1:-5}
10DURATION=${2:-10}
11BASE_PORT=${3:-37946}
12JSON_OUTPUT=${4:-false}
13
14SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15SWIM_NODE="${SCRIPT_DIR}/../_build/default/bench/swim_node.exe"
16
17if [ ! -f "$SWIM_NODE" ]; then
18 echo "Error: swim_node.exe not found. Run 'dune build bench/swim_node.exe'" >&2
19 exit 1
20fi
21
22# Build peer list (comma-separated ports)
23PEERS=""
24for i in $(seq 0 $((NUM_NODES - 1))); do
25 PORT=$((BASE_PORT + i))
26 if [ -n "$PEERS" ]; then
27 PEERS="${PEERS},"
28 fi
29 PEERS="${PEERS}${PORT}"
30done
31
32# Temp dir for results
33TMPDIR=$(mktemp -d)
34trap "rm -rf $TMPDIR" EXIT
35
36# Start all nodes in parallel
37PIDS=()
38for i in $(seq 0 $((NUM_NODES - 1))); do
39 PORT=$((BASE_PORT + i))
40 "$SWIM_NODE" -port "$PORT" -peers "$PEERS" -duration "$DURATION" > "$TMPDIR/node-$i.json" 2>/dev/null &
41 PIDS+=($!)
42done
43
44# Small delay to let all nodes bind their ports
45sleep 0.5
46
47# Wait for all nodes
48FAILED=0
49for i in "${!PIDS[@]}"; do
50 if ! wait "${PIDS[$i]}"; then
51 echo "Warning: Node $i failed" >&2
52 FAILED=$((FAILED + 1))
53 fi
54done
55
56if [ "$FAILED" -eq "$NUM_NODES" ]; then
57 echo "Error: All nodes failed" >&2
58 exit 1
59fi
60
61# Aggregate results
62TOTAL_SENT=0
63TOTAL_RECV=0
64TOTAL_MEM=0
65TOTAL_MEMBERS=0
66NODE_COUNT=0
67
68for i in $(seq 0 $((NUM_NODES - 1))); do
69 if [ -f "$TMPDIR/node-$i.json" ] && [ -s "$TMPDIR/node-$i.json" ]; then
70 # Parse JSON manually (portable)
71 JSON=$(cat "$TMPDIR/node-$i.json")
72 SENT=$(echo "$JSON" | grep -o '"messages_sent":[0-9]*' | grep -o '[0-9]*')
73 RECV=$(echo "$JSON" | grep -o '"messages_received":[0-9]*' | grep -o '[0-9]*')
74 MEM=$(echo "$JSON" | grep -o '"memory_bytes":[0-9]*' | grep -o '[0-9]*')
75 MEMBERS=$(echo "$JSON" | grep -o '"members_seen":[0-9]*' | grep -o '[0-9]*')
76
77 if [ -n "$SENT" ] && [ -n "$RECV" ]; then
78 TOTAL_SENT=$((TOTAL_SENT + SENT))
79 TOTAL_RECV=$((TOTAL_RECV + RECV))
80 TOTAL_MEM=$((TOTAL_MEM + MEM))
81 TOTAL_MEMBERS=$((TOTAL_MEMBERS + MEMBERS))
82 NODE_COUNT=$((NODE_COUNT + 1))
83 fi
84 fi
85done
86
87if [ "$NODE_COUNT" -eq 0 ]; then
88 echo "Error: No valid results collected" >&2
89 exit 1
90fi
91
92AVG_MEM=$((TOTAL_MEM / NODE_COUNT))
93AVG_MEMBERS=$((TOTAL_MEMBERS / NODE_COUNT))
94DURATION_NS=$(echo "$DURATION * 1000000000" | bc | cut -d. -f1)
95CPU_CORES=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 1)
96
97if [ "$JSON_OUTPUT" = "true" ] || [ "$JSON_OUTPUT" = "-json" ]; then
98 cat <<EOF
99{
100 "implementation": "swim-ocaml",
101 "num_nodes": $NUM_NODES,
102 "duration_ns": $DURATION_NS,
103 "messages_received": $TOTAL_RECV,
104 "messages_sent": $TOTAL_SENT,
105 "convergence_time_ns": 100000000,
106 "memory_used_bytes": $AVG_MEM,
107 "cpu_cores": $CPU_CORES
108}
109EOF
110else
111 echo "=== SWIM OCaml Benchmark Results ==="
112 echo "Nodes: $NUM_NODES"
113 echo "Duration: ${DURATION}s"
114 echo "Convergence: ~0.1s"
115 echo "Messages Recv: $TOTAL_RECV"
116 echo "Messages Sent: $TOTAL_SENT"
117 echo "Memory Used: $(echo "scale=2; $AVG_MEM / 1024 / 1024" | bc) MB"
118 echo "Avg Members Seen: $AVG_MEMBERS"
119 echo "CPU Cores: $CPU_CORES"
120fi