import fs from 'fs'; import { execSync } from 'child_process'; const specs = [ { name: 'KafkaKRaft', construct: 'KafkaKRaftMachine::new()', ops: [ 'm.request_vote(2, 1, 0)', 'm.append_entries(2)', 'm.handle_request_vote_request(2, 1, 0, 0)', ]}, { name: 'SQLitePager', construct: 'SQLitePagerMachine::new()', ops: [ 'm.begin_read_transaction()', 'm.begin_write_transaction()', 'm.write_page(1, 100)', 'm.commit_transaction()', ]}, ]; for (const spec of specs) { const { name, construct, ops } = spec; const crateDir = `out/${name}-bench`; // Build crate structure fs.mkdirSync(`${crateDir}/src`, { recursive: true }); fs.mkdirSync(`${crateDir}/benches`, { recursive: true }); // Copy generated lib const libSrc = fs.readFileSync(`out/${name}/src/lib.rs`, 'utf-8'); // Add type defs const typeDefs = `// 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; pub type Bytes = Vec; `; fs.writeFileSync(`${crateDir}/src/lib.rs`, typeDefs + libSrc); // Cargo.toml fs.writeFileSync(`${crateDir}/Cargo.toml`, `[package] name = "${name.toLowerCase()}-bench" version = "0.1.0" edition = "2021" [[bench]] name = "bench" harness = false [profile.bench] debug = 0 lto = "fat" codegen-units = 1 `); // Benchmark code const opBody = ops.map((op, i) => ` let _ = ${op};`).join('\n'); const totalOps = ops.length; fs.writeFileSync(`${crateDir}/benches/bench.rs`, `use std::time::Instant; #[path = "../src/lib.rs"] mod generated; use generated::*; fn main() { let iterations = 100_000; println!("\\n=== ${name} Benchmark ==="); println!("Iterations: {}", iterations); // Instantiation benchmark let start = Instant::now(); for _i in 0..iterations { let _m = ${construct}; } let elapsed = start.elapsed(); let per_inst = elapsed / iterations; let inst_rate = iterations as f64 / elapsed.as_secs_f64(); println!(" Instantiate:"); println!(" Total: {:?}", elapsed); println!(" Per op: {:?}", per_inst); if inst_rate > 1_000_000.0 { println!(" Rate: {:.1} M/sec", inst_rate / 1_000_000.0); } else if inst_rate > 1_000.0 { println!(" Rate: {:.1} K/sec", inst_rate / 1_000.0); } else { println!(" Rate: {:.0}/sec", inst_rate); } // Operation benchmark let total_ops: u64 = iterations * ${totalOps}; let start = Instant::now(); for _i in 0..iterations { let mut m = ${construct}; ${opBody} } let elapsed = start.elapsed(); let per_op = elapsed / total_ops; let rate = total_ops as f64 / elapsed.as_secs_f64(); println!(" Operations ({} ops per cycle):", ${totalOps}); println!(" Total: {:?}", elapsed); println!(" Per op: {:?}", per_op); if rate > 1_000_000.0 { println!(" Rate: {:.1} M ops/sec", rate / 1_000_000.0); } else if rate > 1_000.0 { println!(" Rate: {:.1} K ops/sec", rate / 1_000.0); } else { println!(" Rate: {:.0} ops/sec", rate); } } `); } console.log('Bench crates created. Run: nix-shell -p cargo rustc --run "cd out/KafkaKRaft-bench && cargo bench"'); console.log('And: nix-shell -p cargo rustc --run "cd out/SQLitePager-bench && cargo bench"');