Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
87 lines
3.1 KiB
Bash
Executable File
87 lines
3.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Erlang-on-SX ring benchmark.
|
|
#
|
|
# Spawns N processes in a ring, passes a token N hops (one full round),
|
|
# and reports wall-clock time + throughput. Aspirational target from
|
|
# the plan is 1M processes; current sync-scheduler architecture caps out
|
|
# orders of magnitude lower — this script measures honestly across a
|
|
# range of N so the result/scaling is recorded.
|
|
#
|
|
# Usage:
|
|
# bash lib/erlang/bench_ring.sh # default ladder
|
|
# bash lib/erlang/bench_ring.sh 100 1000 5000 # custom Ns
|
|
|
|
set -uo pipefail
|
|
cd "$(git rev-parse --show-toplevel)"
|
|
|
|
SX_SERVER="${SX_SERVER:-hosts/ocaml/_build/default/bin/sx_server.exe}"
|
|
if [ ! -x "$SX_SERVER" ]; then
|
|
SX_SERVER="/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe"
|
|
fi
|
|
if [ ! -x "$SX_SERVER" ]; then
|
|
echo "ERROR: sx_server.exe not found." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$#" -gt 0 ]; then
|
|
NS=("$@")
|
|
else
|
|
NS=(10 100 500 1000)
|
|
fi
|
|
|
|
TMPFILE=$(mktemp)
|
|
trap "rm -f $TMPFILE" EXIT
|
|
|
|
# One-line Erlang program. Replaces __N__ with the size for each run.
|
|
PROGRAM='Me = self(), N = __N__, Spawner = fun () -> receive {setup, Next} -> Loop = fun () -> receive {token, 0, Parent} -> Parent ! done; {token, K, Parent} -> Next ! {token, K-1, Parent}, Loop() end end, Loop() end end, BuildRing = fun (K, Acc) -> if K =:= 0 -> Acc; true -> BuildRing(K-1, [spawn(Spawner) | Acc]) end end, Pids = BuildRing(N, []), Wire = fun (Ps) -> case Ps of [P, Q | _] -> P ! {setup, Q}, Wire(tl(Ps)); [Last] -> Last ! {setup, hd(Pids)} end end, Wire(Pids), hd(Pids) ! {token, N, Me}, receive done -> done end'
|
|
|
|
run_n() {
|
|
local n="$1"
|
|
local prog="${PROGRAM//__N__/$n}"
|
|
cat > "$TMPFILE" <<EPOCHS
|
|
(epoch 1)
|
|
(load "lib/erlang/tokenizer.sx")
|
|
(load "lib/erlang/parser.sx")
|
|
(load "lib/erlang/parser-core.sx")
|
|
(load "lib/erlang/parser-expr.sx")
|
|
(load "lib/erlang/parser-module.sx")
|
|
(load "lib/erlang/transpile.sx")
|
|
(load "lib/erlang/runtime.sx")
|
|
(epoch 2)
|
|
(eval "(erlang-eval-ast \"${prog//\"/\\\"}\")")
|
|
EPOCHS
|
|
|
|
local start_s start_ns end_s end_ns elapsed_ms
|
|
start_s=$(date +%s)
|
|
start_ns=$(date +%N)
|
|
out=$(timeout 300 "$SX_SERVER" < "$TMPFILE" 2>&1)
|
|
end_s=$(date +%s)
|
|
end_ns=$(date +%N)
|
|
|
|
local ok="false"
|
|
if echo "$out" | grep -q ':name "done"'; then ok="true"; fi
|
|
|
|
# ms = (end_s - start_s)*1000 + (end_ns - start_ns)/1e6
|
|
elapsed_ms=$(awk -v s1="$start_s" -v n1="$start_ns" -v s2="$end_s" -v n2="$end_ns" \
|
|
'BEGIN { printf "%d", (s2 - s1) * 1000 + (n2 - n1) / 1000000 }')
|
|
|
|
if [ "$ok" = "true" ]; then
|
|
local hops_per_s
|
|
hops_per_s=$(awk -v n="$n" -v ms="$elapsed_ms" \
|
|
'BEGIN { if (ms == 0) ms = 1; printf "%.0f", n * 1000 / ms }')
|
|
printf " N=%-8s hops=%-8s %sms (%s hops/s)\n" "$n" "$n" "$elapsed_ms" "$hops_per_s"
|
|
else
|
|
printf " N=%-8s FAILED %sms\n" "$n" "$elapsed_ms"
|
|
fi
|
|
}
|
|
|
|
echo "Ring benchmark — sx_server.exe (synchronous scheduler)"
|
|
echo
|
|
for n in "${NS[@]}"; do
|
|
run_n "$n"
|
|
done
|
|
echo
|
|
echo "Note: 1M-process target from the plan is aspirational; the synchronous"
|
|
echo "scheduler with shift-based suspension and dict-based env copies is not"
|
|
echo "engineered for that scale. Numbers above are honest baselines."
|