use seerdb::{DBOptions, SyncPolicy};
use std::time::Instant;
use tempfile::tempdir;
fn main() {
println!("=== Transaction Commit Profiling ===\n");
let dir = tempdir().unwrap();
let db = DBOptions::default()
.memtable_capacity(128 * 1024 * 1024)
.sync_policy(SyncPolicy::None)
.background_compaction(true)
.background_flush(true)
.open(dir.path())
.unwrap();
for i in 0..1000 {
let key = format!("key_{:06}", i);
db.put(key.as_bytes(), b"initial_value").unwrap();
}
let iterations = 10_000;
println!("Profile 1: Write-only transactions (no read-set validation)");
let start = Instant::now();
for i in 0..iterations {
let mut txn = db.begin_transaction();
let key = format!("new_key_{:06}", i);
txn.put(key.as_bytes(), b"value").unwrap();
txn.commit().unwrap();
}
let write_only_time = start.elapsed();
println!(
" {} iterations in {:?} ({:.0} txn/sec)\n",
iterations,
write_only_time,
iterations as f64 / write_only_time.as_secs_f64()
);
println!("Profile 2: Read-then-write transactions (1 read in read-set)");
let start = Instant::now();
for i in 0..iterations {
let mut txn = db.begin_transaction();
let read_key = format!("key_{:06}", i % 1000);
let _ = txn.get(read_key.as_bytes());
let write_key = format!("rw_key_{:06}", i);
txn.put(write_key.as_bytes(), b"value").unwrap();
txn.commit().unwrap();
}
let read_write_time = start.elapsed();
println!(
" {} iterations in {:?} ({:.0} txn/sec)\n",
iterations,
read_write_time,
iterations as f64 / read_write_time.as_secs_f64()
);
println!("Profile 3: Read-heavy transactions (10 reads in read-set)");
let start = Instant::now();
for i in 0..iterations {
let mut txn = db.begin_transaction();
for j in 0..10 {
let read_key = format!("key_{:06}", (i * 10 + j) % 1000);
let _ = txn.get(read_key.as_bytes());
}
let write_key = format!("rh_key_{:06}", i);
txn.put(write_key.as_bytes(), b"value").unwrap();
txn.commit().unwrap();
}
let read_heavy_time = start.elapsed();
println!(
" {} iterations in {:?} ({:.0} txn/sec)\n",
iterations,
read_heavy_time,
iterations as f64 / read_heavy_time.as_secs_f64()
);
println!("Profile 4: Batch transactions (10 writes per txn)");
let start = Instant::now();
for i in 0..(iterations / 10) {
let mut txn = db.begin_transaction();
for j in 0..10 {
let key = format!("batch_key_{:06}_{}", i, j);
txn.put(key.as_bytes(), b"value").unwrap();
}
txn.commit().unwrap();
}
let batch_time = start.elapsed();
println!(
" {} txns ({} writes) in {:?} ({:.0} writes/sec)\n",
iterations / 10,
iterations,
batch_time,
iterations as f64 / batch_time.as_secs_f64()
);
println!("Profile 5: Raw puts (no transaction)");
let start = Instant::now();
for i in 0..iterations {
let key = format!("raw_key_{:06}", i);
db.put(key.as_bytes(), b"value").unwrap();
}
let raw_time = start.elapsed();
println!(
" {} iterations in {:?} ({:.0} ops/sec)\n",
iterations,
raw_time,
iterations as f64 / raw_time.as_secs_f64()
);
println!("=== Summary ===");
println!(
"Write-only txn: {:.0} txn/sec",
iterations as f64 / write_only_time.as_secs_f64()
);
println!(
"Read-write txn: {:.0} txn/sec ({:.1}x slower)",
iterations as f64 / read_write_time.as_secs_f64(),
read_write_time.as_secs_f64() / write_only_time.as_secs_f64()
);
println!(
"Read-heavy txn: {:.0} txn/sec ({:.1}x slower)",
iterations as f64 / read_heavy_time.as_secs_f64(),
read_heavy_time.as_secs_f64() / write_only_time.as_secs_f64()
);
println!(
"Batch txn (10): {:.0} writes/sec ({:.1}x faster)",
iterations as f64 / batch_time.as_secs_f64(),
write_only_time.as_secs_f64() / batch_time.as_secs_f64()
);
println!(
"Raw put: {:.0} ops/sec",
iterations as f64 / raw_time.as_secs_f64()
);
println!(
"\nTransaction overhead vs raw: {:.1}%",
(write_only_time.as_secs_f64() / raw_time.as_secs_f64() - 1.0) * 100.0
);
}