From 3a861e1618f1064791c6b19fea8e05c0ad37afc6 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Tue, 15 Jul 2025 13:37:55 +0300 Subject: [PATCH] bench: add insert benchmark (batch sizes: 1,10,100) --- core/benches/benchmark.rs | 102 +++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/core/benches/benchmark.rs b/core/benches/benchmark.rs index e864e35fb..8871dc566 100644 --- a/core/benches/benchmark.rs +++ b/core/benches/benchmark.rs @@ -271,9 +271,109 @@ fn bench_execute_select_count(criterion: &mut Criterion) { group.finish(); } +fn bench_insert_rows(criterion: &mut Criterion) { + // The rusqlite benchmark crashes on Mac M1 when using the flamegraph features + let enable_rusqlite = std::env::var("DISABLE_RUSQLITE_BENCHMARK").is_err(); + + let mut group = criterion.benchmark_group("Insert rows in batches"); + + // Test different batch sizes + for batch_size in [1, 10, 100] { + let temp_dir = tempfile::tempdir().unwrap(); + let db_path = temp_dir.path().join("bench.db"); + + #[allow(clippy::arc_with_non_send_sync)] + let io = Arc::new(PlatformIO::new().unwrap()); + let db = Database::open_file(io.clone(), db_path.to_str().unwrap(), false, false).unwrap(); + let limbo_conn = db.connect().unwrap(); + + let mut stmt = limbo_conn + .query("CREATE TABLE test (id INTEGER, value TEXT)") + .unwrap() + .unwrap(); + + loop { + match stmt.step().unwrap() { + turso_core::StepResult::IO => { + stmt.run_once().unwrap(); + } + turso_core::StepResult::Done => { + break; + } + turso_core::StepResult::Row => { + unreachable!(); + } + turso_core::StepResult::Interrupt | turso_core::StepResult::Busy => { + unreachable!(); + } + } + } + + group.bench_function(format!("limbo_insert_{batch_size}_rows"), |b| { + let mut values = String::from("INSERT INTO test VALUES "); + for i in 0..batch_size { + if i > 0 { + values.push(','); + } + values.push_str(&format!("({}, '{}')", i, format_args!("value_{i}"))); + } + let mut stmt = limbo_conn.prepare(&values).unwrap(); + b.iter(|| { + loop { + match stmt.step().unwrap() { + turso_core::StepResult::IO => { + stmt.run_once().unwrap(); + } + turso_core::StepResult::Done => { + break; + } + turso_core::StepResult::Row => { + unreachable!(); + } + turso_core::StepResult::Interrupt | turso_core::StepResult::Busy => { + unreachable!(); + } + } + } + stmt.reset(); + }); + }); + + if enable_rusqlite { + let temp_dir = tempfile::tempdir().unwrap(); + let db_path = temp_dir.path().join("bench.db"); + let sqlite_conn = rusqlite::Connection::open(db_path).unwrap(); + + // Create test table + sqlite_conn + .execute("CREATE TABLE test (id INTEGER, value TEXT)", []) + .unwrap(); + + group.bench_function(format!("sqlite_insert_{batch_size}_rows"), |b| { + let mut values = String::from("INSERT INTO test VALUES "); + for i in 0..batch_size { + if i > 0 { + values.push(','); + } + values.push_str(&format!("({}, '{}')", i, format_args!("value_{i}"))); + } + let mut stmt = sqlite_conn.prepare(&values).unwrap(); + b.iter(|| { + let mut rows = stmt.raw_query(); + while let Some(row) = rows.next().unwrap() { + black_box(row); + } + }); + }); + } + } + + group.finish(); +} + criterion_group! { name = benches; config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); - targets = bench_open, bench_prepare_query, bench_execute_select_1, bench_execute_select_rows, bench_execute_select_count + targets = bench_open, bench_prepare_query, bench_execute_select_1, bench_execute_select_rows, bench_execute_select_count, bench_insert_rows } criterion_main!(benches);