136 lines
3.5 KiB
Bash
Executable File
136 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SYMCLAW="${SYMCLAW_BIN:-./target/release/symclaw}"
|
|
TOTAL="${STRESS_COUNT:-1000}"
|
|
CONCURRENCY="${STRESS_CONCURRENCY:-20}"
|
|
RESULTS_DIR=$(mktemp -d)
|
|
FAILURES=0
|
|
OOM_COUNT=0
|
|
|
|
if [[ ! -x "$SYMCLAW" ]]; then
|
|
echo "ERROR: symclaw binary not found at $SYMCLAW"
|
|
echo "Build with: cargo build --release -p symclaw-cli"
|
|
exit 1
|
|
fi
|
|
|
|
echo "=== SymClaw Stress Test ==="
|
|
echo "Binary: $SYMCLAW"
|
|
echo "Expressions: $TOTAL (concurrency: $CONCURRENCY)"
|
|
echo "Results dir: $RESULTS_DIR"
|
|
echo ""
|
|
|
|
# Expression generators
|
|
expressions=(
|
|
"diff(x^2 + 3*x + 1, x)"
|
|
"diff(sin(x)*cos(x), x)"
|
|
"diff(e^(x^2), x)"
|
|
"simplify((x^2 - 1)/(x - 1))"
|
|
"simplify(sin(x)^2 + cos(x)^2)"
|
|
"expand((x + y)^4)"
|
|
"expand((a + b + c)^3)"
|
|
"factor(x^4 - 1)"
|
|
"diff(ln(x^2 + 1), x)"
|
|
"simplify((x^3 - 8)/(x - 2))"
|
|
"diff(tan(x), x)"
|
|
"expand((x + 1)^6)"
|
|
"simplify(x^2*x^3)"
|
|
"diff(x^x, x)"
|
|
"simplify((a^2 - b^2)/(a + b))"
|
|
"expand((1 + x + x^2)^2)"
|
|
"diff(sin(cos(tan(x))), x)"
|
|
"simplify(sqrt(x^2))"
|
|
"diff(e^(sin(x)), x)"
|
|
"expand((x - y)^5)"
|
|
)
|
|
|
|
num_exprs=${#expressions[@]}
|
|
|
|
run_one() {
|
|
local id=$1
|
|
local expr=${expressions[$((RANDOM % num_exprs))]}
|
|
local outfile="$RESULTS_DIR/$id"
|
|
|
|
local start_ns
|
|
start_ns=$(date +%s%N)
|
|
|
|
local exit_code=0
|
|
timeout 30 "$SYMCLAW" eval "$expr" > "$outfile.out" 2> "$outfile.err" || exit_code=$?
|
|
|
|
local end_ns
|
|
end_ns=$(date +%s%N)
|
|
local elapsed_ms=$(( (end_ns - start_ns) / 1000000 ))
|
|
|
|
echo "$id $exit_code $elapsed_ms" >> "$RESULTS_DIR/timings.log"
|
|
|
|
if [[ $exit_code -ne 0 ]]; then
|
|
if grep -qi "out of memory\|oom\|alloc" "$outfile.err" 2>/dev/null; then
|
|
echo "OOM" >> "$RESULTS_DIR/oom.log"
|
|
fi
|
|
echo "FAIL" >> "$RESULTS_DIR/failures.log"
|
|
fi
|
|
}
|
|
|
|
export -f run_one
|
|
export SYMCLAW RESULTS_DIR expressions num_exprs
|
|
|
|
# Initialize log files
|
|
> "$RESULTS_DIR/timings.log"
|
|
> "$RESULTS_DIR/failures.log"
|
|
> "$RESULTS_DIR/oom.log"
|
|
|
|
echo "Running $TOTAL expressions..."
|
|
seq 1 "$TOTAL" | xargs -P "$CONCURRENCY" -I{} bash -c 'run_one {}'
|
|
|
|
# Collect results
|
|
FAILURES=$(wc -l < "$RESULTS_DIR/failures.log")
|
|
OOM_COUNT=$(wc -l < "$RESULTS_DIR/oom.log")
|
|
SUCCESSES=$((TOTAL - FAILURES))
|
|
|
|
# Calculate latency percentiles
|
|
if [[ -s "$RESULTS_DIR/timings.log" ]]; then
|
|
latencies=$(awk '{print $3}' "$RESULTS_DIR/timings.log" | sort -n)
|
|
count=$(echo "$latencies" | wc -l)
|
|
|
|
p50_idx=$(( count * 50 / 100 ))
|
|
p95_idx=$(( count * 95 / 100 ))
|
|
p99_idx=$(( count * 99 / 100 ))
|
|
[ "$p50_idx" -lt 1 ] && p50_idx=1
|
|
[ "$p95_idx" -lt 1 ] && p95_idx=1
|
|
[ "$p99_idx" -lt 1 ] && p99_idx=1
|
|
|
|
p50=$(echo "$latencies" | sed -n "${p50_idx}p")
|
|
p95=$(echo "$latencies" | sed -n "${p95_idx}p")
|
|
p99=$(echo "$latencies" | sed -n "${p99_idx}p")
|
|
avg=$(echo "$latencies" | awk '{s+=$1}END{printf "%.0f", s/NR}')
|
|
max_lat=$(echo "$latencies" | tail -1)
|
|
min_lat=$(echo "$latencies" | head -1)
|
|
fi
|
|
|
|
echo ""
|
|
echo "=== Results ==="
|
|
echo "Total: $TOTAL"
|
|
echo "Success: $SUCCESSES ($((SUCCESSES * 100 / TOTAL))%)"
|
|
echo "Failures: $FAILURES"
|
|
echo "OOM: $OOM_COUNT"
|
|
echo ""
|
|
echo "=== Latency (ms) ==="
|
|
echo "Min: ${min_lat:-N/A}"
|
|
echo "Avg: ${avg:-N/A}"
|
|
echo "p50: ${p50:-N/A}"
|
|
echo "p95: ${p95:-N/A}"
|
|
echo "p99: ${p99:-N/A}"
|
|
echo "Max: ${max_lat:-N/A}"
|
|
|
|
# Cleanup
|
|
rm -rf "$RESULTS_DIR"
|
|
|
|
if [[ "$FAILURES" -gt 0 ]]; then
|
|
echo ""
|
|
echo "⚠ $FAILURES failures detected"
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
echo "✓ All expressions evaluated successfully"
|