#!/bin/bash # Benchmark Speck-generated Rust output set -e cd /home/sscoble/speckl regen=0 bench_spec() { local SPEC=$1 local BENCH_DIR="out/${SPEC}-bench" local PROLOGUE=$2 local CONSTRUCT=$3 local OPS=$4 echo "=== $SPEC ===" if [ "$regen" -eq 1 ]; then node compiler/dist/index.js "examples/$SPEC.speck" --target=rust 2>/dev/null fi mkdir -p "$BENCH_DIR/src" cp "out/$SPEC/src/lib.rs" "$BENCH_DIR/src/lib.rs" # Add type defs and fix Option syntax cat > "$BENCH_DIR/src/lib_patched.rs" << 'EOF' // Auto-generated type definitions pub type NodeId = u64; pub type LogEntry = String; pub type Account = String; pub type Transfer = String; pub type TransferId = u64; pub type PageId = u64; pub type PageData = u64; pub type Frame = u64; pub type FrameId = u64; EOF cat "$BENCH_DIR/src/lib.rs" >> "$BENCH_DIR/src/lib_patched.rs" mv "$BENCH_DIR/src/lib_patched.rs" "$BENCH_DIR/src/lib.rs" # Create Cargo.toml with benchmark profile cat > "$BENCH_DIR/Cargo.toml" << 'CTOML' [package] name = "speck-bench" version = "0.1.0" edition = "2021" [[bench]] name = "bench" harness = false [profile.bench] debug = 0 lto = "fat" codegen-units = 1 CTOML # Create benchmark mkdir -p "$BENCH_DIR/benches" cat > "$BENCH_DIR/benches/bench.rs" << 'BRS' use std::time::{Duration, Instant}; #[path = "../src/lib.rs"] mod generated; BRS # Add spec-specific benchmark { echo "use generated::*;" echo "" echo "fn main() {" echo " let iterations = 100000;" echo " println!(\"Benchmarking $SPEC...\");" echo "" echo " // Instantiation benchmark" echo " let start = Instant::now();" echo " for i in 0..iterations {" echo " let mut m = $CONSTRUCT;" echo " let _ = m;" echo " }" echo " let elapsed = start.elapsed();" echo " let per = elapsed / iterations;" echo " println!(\" Instantiate x{}:\", iterations);" echo " println!(\" Total: {:?}\", elapsed);" echo " println!(\" Per op: {:?}\", per);" echo " println!(\" Ops/sec: {:.0}\", iterations as f64 / elapsed.as_secs_f64());" echo "" echo " // Operational benchmark" echo " let mut total_ops = 0u64;" echo " let start = Instant::now();" echo " for i in 0..iterations {" echo $PROLOGUE echo " }" echo " let elapsed = start.elapsed();" echo " let per = elapsed / total_ops;" echo " println!(\" Operations x{} ({} ops):\", iterations, total_ops);" echo " let rate = total_ops as f64 / elapsed.as_secs_f64();" echo " println!(\" Total: {:?}\", elapsed);" echo " println!(\" Per op: {:?}\", per);" echo " if rate > 1_000_000.0 {" echo " println!(\" Rate: {:.0} M ops/sec\", rate / 1_000_000.0);" echo " } else if rate > 1_000.0 {" echo " println!(\" Rate: {:.0} K ops/sec\", rate / 1_000.0);" echo " } else {" echo " println!(\" Rate: {:.0} ops/sec\", rate);" echo " }" echo "}" } >> "$BENCH_DIR/benches/bench.rs" } # KafkaKRaft benchmark bench_spec "KafkaKRaft" \ ' let mut m = KafkaKRaftMachine::new(); let _ = m.request_vote(2, 1, 0); let _ = m.append_entries(2); let _ = m.handle_request_vote_request(2, 1, 0, 0); total_ops += 3;' \ 'KafkaKRaftMachine::new()' \ 3 # SQLitePager benchmark bench_spec "SQLitePager" \ ' let mut m = SQLitePagerMachine::new(); let _ = m.begin_read_transaction(); let _ = m.begin_write_transaction(); let _ = m.write_page(1, 100); let _ = m.commit_transaction(); total_ops += 4;' \ 'SQLitePagerMachine::new()' \ 4 # TigerBeetleLedger benchmark bench_spec "TigerBeetleLedger" \ ' let mut m = TigerBeetleLedgerMachine::new(); let _ = m.create_account(1, 1000, 0); let _ = m.create_account(2, 0, 0); let _ = m.create_transfer(1, 1, 2, 100, 0); total_ops += 3;' \ 'TigerBeetleLedgerMachine::new()' \ 3 echo "" echo "=== Building benchmarks ===" for D in out/KafkaKRaft-bench out/SQLitePager-bench out/TigerBeetleLedger-bench; do echo "Building $D..." (cd "$D" && cargo bench --no-run 2>&1 | tail -5) done echo "" echo "=== Running benchmarks ===" for D in out/KafkaKRaft-bench out/SQLitePager-bench out/TigerBeetleLedger-bench; do echo "" (cd "$D" && cargo bench 2>&1) done