|
| 1 | +#!/usr/bin/env bash |
| 2 | +# |
| 3 | +# Run all tsb (TypeScript) and pandas (Python) benchmarks and collect results. |
| 4 | +# |
| 5 | +# Usage: ./benchmarks/run_benchmarks.sh |
| 6 | +# |
| 7 | +# Outputs: benchmarks/results.json with all benchmark results |
| 8 | +# |
| 9 | +set -euo pipefail |
| 10 | + |
| 11 | +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 12 | +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" |
| 13 | + |
| 14 | +# Ensure Python and pandas are available |
| 15 | +if ! command -v python3 &>/dev/null; then |
| 16 | + echo "ERROR: python3 is required but not found" >&2 |
| 17 | + exit 1 |
| 18 | +fi |
| 19 | + |
| 20 | +python3 -c "import pandas" 2>/dev/null || { |
| 21 | + echo "Installing pandas..." |
| 22 | + pip3 install pandas --quiet |
| 23 | +} |
| 24 | + |
| 25 | +# Ensure Bun is available |
| 26 | +if ! command -v bun &>/dev/null; then |
| 27 | + echo "ERROR: bun is required but not found" >&2 |
| 28 | + exit 1 |
| 29 | +fi |
| 30 | + |
| 31 | +# Collect results |
| 32 | +results='{"benchmarks": [], "timestamp": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'"}' |
| 33 | + |
| 34 | +echo "=== Running Performance Benchmarks ===" |
| 35 | +echo "" |
| 36 | + |
| 37 | +# Find all TypeScript benchmark files |
| 38 | +for ts_bench in "$SCRIPT_DIR"/tsb/bench_*.ts; do |
| 39 | + [ -f "$ts_bench" ] || continue |
| 40 | + bench_name=$(basename "$ts_bench" .ts | sed 's/^bench_//') |
| 41 | + |
| 42 | + # Check for matching Python benchmark |
| 43 | + py_bench="$SCRIPT_DIR/pandas/bench_${bench_name}.py" |
| 44 | + if [ ! -f "$py_bench" ]; then |
| 45 | + echo "SKIP: $bench_name (no matching Python benchmark)" |
| 46 | + continue |
| 47 | + fi |
| 48 | + |
| 49 | + echo "--- Benchmarking: $bench_name ---" |
| 50 | + |
| 51 | + # Run TypeScript benchmark |
| 52 | + echo " Running tsb (TypeScript)..." |
| 53 | + ts_result=$(cd "$REPO_ROOT" && bun run "$ts_bench" 2>/dev/null) || { |
| 54 | + echo " ERROR: TypeScript benchmark failed" |
| 55 | + continue |
| 56 | + } |
| 57 | + echo " tsb result: $ts_result" |
| 58 | + |
| 59 | + # Run Python benchmark |
| 60 | + echo " Running pandas (Python)..." |
| 61 | + py_result=$(cd "$REPO_ROOT" && python3 "$py_bench" 2>/dev/null) || { |
| 62 | + echo " ERROR: Python benchmark failed" |
| 63 | + continue |
| 64 | + } |
| 65 | + echo " pandas result: $py_result" |
| 66 | + |
| 67 | + # Extract mean_ms from both |
| 68 | + ts_mean=$(echo "$ts_result" | python3 -c "import sys, json; d=json.load(sys.stdin); print(d['mean_ms'])" 2>/dev/null) || { |
| 69 | + echo " ERROR: could not parse tsb benchmark result" |
| 70 | + continue |
| 71 | + } |
| 72 | + py_mean=$(echo "$py_result" | python3 -c "import sys, json; d=json.load(sys.stdin); print(d['mean_ms'])" 2>/dev/null) || { |
| 73 | + echo " ERROR: could not parse pandas benchmark result" |
| 74 | + continue |
| 75 | + } |
| 76 | + |
| 77 | + # Calculate ratio (tsb / pandas) — < 1.0 means tsb is faster |
| 78 | + ratio=$(python3 -c " |
| 79 | +ts, py = $ts_mean, $py_mean |
| 80 | +if py <= 0: |
| 81 | + print('null') |
| 82 | +else: |
| 83 | + print(round(ts / py, 3)) |
| 84 | +") |
| 85 | + if [ "$ratio" = "null" ]; then |
| 86 | + echo " ERROR: pandas mean_ms is zero, cannot compute ratio" |
| 87 | + continue |
| 88 | + fi |
| 89 | + |
| 90 | + echo " Ratio (tsb/pandas): ${ratio}x" |
| 91 | + echo "" |
| 92 | + |
| 93 | + # Add to results JSON |
| 94 | + results=$(echo "$results" | python3 -c " |
| 95 | +import sys, json |
| 96 | +data = json.load(sys.stdin) |
| 97 | +data['benchmarks'].append({ |
| 98 | + 'function': '$bench_name', |
| 99 | + 'tsb': $ts_result, |
| 100 | + 'pandas': $py_result, |
| 101 | + 'ratio': $ratio |
| 102 | +}) |
| 103 | +print(json.dumps(data, indent=2)) |
| 104 | +") |
| 105 | +done |
| 106 | + |
| 107 | +# Write results |
| 108 | +echo "$results" > "$SCRIPT_DIR/results.json" |
| 109 | +echo "=== Results written to benchmarks/results.json ===" |
| 110 | +echo "" |
| 111 | + |
| 112 | +# Summary |
| 113 | +echo "=== Summary ===" |
| 114 | +echo "$results" | python3 -c " |
| 115 | +import sys, json |
| 116 | +data = json.load(sys.stdin) |
| 117 | +benchmarks = data.get('benchmarks', []) |
| 118 | +if not benchmarks: |
| 119 | + print('No benchmarks found.') |
| 120 | +else: |
| 121 | + print(f'Functions benchmarked: {len(benchmarks)}') |
| 122 | + for b in benchmarks: |
| 123 | + fn = b['function'] |
| 124 | + ts = b['tsb']['mean_ms'] |
| 125 | + py = b['pandas']['mean_ms'] |
| 126 | + ratio = b['ratio'] |
| 127 | + faster = 'tsb' if ratio < 1 else 'pandas' |
| 128 | + print(f' {fn}: tsb={ts}ms, pandas={py}ms, ratio={ratio}x ({faster} is faster)') |
| 129 | +" |
0 commit comments