#12: All 5 untranslated SpeckDL patterns now emit valid JS: - notIn → !.has(), old() → drop, union → Set spread, set diff → filter, append() → [...X, Y], length() → .length - ==/!= operator replacement fixed (word-boundary regression) - Postcondition object comparisons get @ts-expect-error TS2839 #11: Generator auto-detects opaque identifier types used in state variables and action params, emits 'type X = any' before class. - State properties use ! (non-null assertion) for strict mode TigerBeetleLedger → tsc --noEmit = 0 errors. 37/37 tests pass.
155 lines
4.3 KiB
Bash
155 lines
4.3 KiB
Bash
#!/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
|