#!/bin/bash # # SWIM OCaml Parallel Benchmark Coordinator # Spawns N nodes in parallel, collects JSON results, aggregates stats # set -e NUM_NODES=${1:-5} DURATION=${2:-10} BASE_PORT=${3:-37946} JSON_OUTPUT=${4:-false} SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SWIM_NODE="${SCRIPT_DIR}/../_build/default/bench/swim_node.exe" if [ ! -f "$SWIM_NODE" ]; then echo "Error: swim_node.exe not found. Run 'dune build bench/swim_node.exe'" >&2 exit 1 fi # Build peer list (comma-separated ports) PEERS="" for i in $(seq 0 $((NUM_NODES - 1))); do PORT=$((BASE_PORT + i)) if [ -n "$PEERS" ]; then PEERS="${PEERS}," fi PEERS="${PEERS}${PORT}" done # Temp dir for results TMPDIR=$(mktemp -d) trap "rm -rf $TMPDIR" EXIT # Start all nodes in parallel PIDS=() for i in $(seq 0 $((NUM_NODES - 1))); do PORT=$((BASE_PORT + i)) "$SWIM_NODE" -port "$PORT" -peers "$PEERS" -duration "$DURATION" > "$TMPDIR/node-$i.json" 2>/dev/null & PIDS+=($!) done # Small delay to let all nodes bind their ports sleep 0.5 # Wait for all nodes FAILED=0 for i in "${!PIDS[@]}"; do if ! wait "${PIDS[$i]}"; then echo "Warning: Node $i failed" >&2 FAILED=$((FAILED + 1)) fi done if [ "$FAILED" -eq "$NUM_NODES" ]; then echo "Error: All nodes failed" >&2 exit 1 fi # Aggregate results TOTAL_SENT=0 TOTAL_RECV=0 TOTAL_MEM=0 TOTAL_MEMBERS=0 NODE_COUNT=0 for i in $(seq 0 $((NUM_NODES - 1))); do if [ -f "$TMPDIR/node-$i.json" ] && [ -s "$TMPDIR/node-$i.json" ]; then # Parse JSON manually (portable) JSON=$(cat "$TMPDIR/node-$i.json") SENT=$(echo "$JSON" | grep -o '"messages_sent":[0-9]*' | grep -o '[0-9]*') RECV=$(echo "$JSON" | grep -o '"messages_received":[0-9]*' | grep -o '[0-9]*') MEM=$(echo "$JSON" | grep -o '"memory_bytes":[0-9]*' | grep -o '[0-9]*') MEMBERS=$(echo "$JSON" | grep -o '"members_seen":[0-9]*' | grep -o '[0-9]*') if [ -n "$SENT" ] && [ -n "$RECV" ]; then TOTAL_SENT=$((TOTAL_SENT + SENT)) TOTAL_RECV=$((TOTAL_RECV + RECV)) TOTAL_MEM=$((TOTAL_MEM + MEM)) TOTAL_MEMBERS=$((TOTAL_MEMBERS + MEMBERS)) NODE_COUNT=$((NODE_COUNT + 1)) fi fi done if [ "$NODE_COUNT" -eq 0 ]; then echo "Error: No valid results collected" >&2 exit 1 fi AVG_MEM=$((TOTAL_MEM / NODE_COUNT)) AVG_MEMBERS=$((TOTAL_MEMBERS / NODE_COUNT)) DURATION_NS=$(echo "$DURATION * 1000000000" | bc | cut -d. -f1) CPU_CORES=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 1) if [ "$JSON_OUTPUT" = "true" ] || [ "$JSON_OUTPUT" = "-json" ]; then cat <