diff --git a/database/benchmark/benches/db.rs b/database/benchmark/benches/db.rs index 38718350..88c28cab 100644 --- a/database/benchmark/benches/db.rs +++ b/database/benchmark/benches/db.rs @@ -1,5 +1,7 @@ //! TODO +use std::time::Instant; + //---------------------------------------------------------------------------------------------------- Import use criterion::{black_box, criterion_group, criterion_main, Criterion}; @@ -14,7 +16,29 @@ use cuprate_database::{ use cuprate_database_benchmark::tmp_concrete_env; //---------------------------------------------------------------------------------------------------- Criterion -criterion_group!(benches, put, get, get_range, delete); +criterion_group! { + benches, + ro_get, + ro_len, + ro_first, + ro_last, + ro_is_empty, + ro_contains, + rw_get, + rw_len, + rw_first, + rw_last, + rw_is_empty, + rw_contains, + put, + delete, + pop_first, + pop_last, + get_range, + iter, + keys, + values, +} criterion_main!(benches); //---------------------------------------------------------------------------------------------------- Constants @@ -32,7 +56,283 @@ const VALUE: Output = Output { tx_idx: 2_353_487, }; -//---------------------------------------------------------------------------------------------------- Env benchmarks +//---------------------------------------------------------------------------------------------------- DatabaseRo +// Read-only table operations. +// This uses `TxRw + TablesMut` briefly to insert values, then +// uses `TxRo + Tables` for the actual operation. +// +// See further below for using `TxRw + TablesMut` on the same operations. + +/// [`DatabaseRo::get`] +#[named] +fn ro_get(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + table.put(&KEY, &VALUE).unwrap(); + drop(table); + tx_rw.commit().unwrap(); + + let tx_ro = env_inner.tx_ro().unwrap(); + let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + let _value: Output = table.get(black_box(&KEY)).unwrap(); + }); + }); +} + +/// [`DatabaseRo::len`] +#[named] +fn ro_len(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + table.put(&KEY, &VALUE).unwrap(); + drop(table); + tx_rw.commit().unwrap(); + + let tx_ro = env_inner.tx_ro().unwrap(); + let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + black_box(table.len()).unwrap(); + }); + }); +} + +/// [`DatabaseRo::first`] +#[named] +fn ro_first(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + table.put(&KEY, &VALUE).unwrap(); + drop(table); + tx_rw.commit().unwrap(); + + let tx_ro = env_inner.tx_ro().unwrap(); + let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + let (_, _): (PreRctOutputId, Output) = black_box(table.first()).unwrap(); + }); + }); +} + +/// [`DatabaseRo::last`] +#[named] +fn ro_last(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + table.put(&KEY, &VALUE).unwrap(); + drop(table); + tx_rw.commit().unwrap(); + + let tx_ro = env_inner.tx_ro().unwrap(); + let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + let (_, _): (PreRctOutputId, Output) = black_box(table.last()).unwrap(); + }); + }); +} + +/// [`DatabaseRo::is_empty`] +#[named] +fn ro_is_empty(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + table.put(&KEY, &VALUE).unwrap(); + drop(table); + tx_rw.commit().unwrap(); + + let tx_ro = env_inner.tx_ro().unwrap(); + let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + black_box(table.is_empty()).unwrap(); + }); + }); +} + +/// [`DatabaseRo::contains`] +#[named] +fn ro_contains(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + table.put(&KEY, &VALUE).unwrap(); + drop(table); + tx_rw.commit().unwrap(); + + let tx_ro = env_inner.tx_ro().unwrap(); + let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + table.contains(black_box(&KEY)).unwrap(); + }); + }); +} + +//---------------------------------------------------------------------------------------------------- DatabaseRo (using TxRw) +// These are the same benchmarks as above, but it uses a +// `TxRw` and a `TablesMut` instead to ensure our read/write tables +// using read operations perform the same as normal read-only tables. + +/// [`DatabaseRo::get`] +#[named] +fn rw_get(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + table.put(&KEY, &VALUE).unwrap(); + drop(table); + tx_rw.commit().unwrap(); + + let tx_rw = env_inner.tx_rw().unwrap(); + let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + let _value: Output = table.get(black_box(&KEY)).unwrap(); + }); + }); +} + +/// [`DatabaseRo::len`] +#[named] +fn rw_len(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + table.put(&KEY, &VALUE).unwrap(); + drop(table); + tx_rw.commit().unwrap(); + + let tx_rw = env_inner.tx_rw().unwrap(); + let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + black_box(table.len()).unwrap(); + }); + }); +} + +/// [`DatabaseRo::first`] +#[named] +fn rw_first(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + table.put(&KEY, &VALUE).unwrap(); + drop(table); + tx_rw.commit().unwrap(); + + let tx_rw = env_inner.tx_rw().unwrap(); + let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + let (_, _): (PreRctOutputId, Output) = black_box(table.first()).unwrap(); + }); + }); +} + +/// [`DatabaseRo::last`] +#[named] +fn rw_last(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + table.put(&KEY, &VALUE).unwrap(); + drop(table); + tx_rw.commit().unwrap(); + + let tx_rw = env_inner.tx_rw().unwrap(); + let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + let (_, _): (PreRctOutputId, Output) = black_box(table.last()).unwrap(); + }); + }); +} + +/// [`DatabaseRo::is_empty`] +#[named] +fn rw_is_empty(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + table.put(&KEY, &VALUE).unwrap(); + drop(table); + tx_rw.commit().unwrap(); + + let tx_rw = env_inner.tx_rw().unwrap(); + let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + black_box(table.is_empty()).unwrap(); + }); + }); +} + +/// [`DatabaseRo::contains`] +#[named] +fn rw_contains(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + table.put(&KEY, &VALUE).unwrap(); + drop(table); + tx_rw.commit().unwrap(); + + let tx_rw = env_inner.tx_rw().unwrap(); + let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + table.contains(black_box(&KEY)).unwrap(); + }); + }); +} + +//---------------------------------------------------------------------------------------------------- DatabaseRw /// [`DatabaseRw::put`] #[named] fn put(c: &mut Criterion) { @@ -51,23 +351,117 @@ fn put(c: &mut Criterion) { }); } -/// [`DatabaseRo::get`] +/// [`DatabaseRw::delete`] #[named] -fn get(c: &mut Criterion) { +fn delete(c: &mut Criterion) { let (env, _tempdir) = tmp_concrete_env(); let env_inner = env.env_inner(); let tx_rw = env_inner.tx_rw().unwrap(); let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); - table.put(&KEY, &VALUE).unwrap(); + let mut key = KEY; c.bench_function(function_name!(), |b| { - b.iter(|| { - let _value: Output = table.get(black_box(&KEY)).unwrap(); + b.iter_custom(|iters| { + for _ in 0..iters { + table.put(&key, &VALUE).unwrap(); + key.amount += 1; + } + + key = KEY; + + let start = Instant::now(); + for _ in 0..iters { + table.delete(&key).unwrap(); + key.amount += 1; + } + start.elapsed() }); }); } +/// [`DatabaseRw::pop_first`] +#[named] +fn pop_first(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + let mut key = KEY; + + c.bench_function(function_name!(), |b| { + b.iter_custom(|iters| { + for _ in 0..iters { + table.put(&key, &VALUE).unwrap(); + key.amount += 1; + } + + key = KEY; + + let start = Instant::now(); + for _ in 0..iters { + table.pop_first().unwrap(); + key.amount += 1; + } + start.elapsed() + }); + }); +} + +/// [`DatabaseRw::pop_last`] +#[named] +fn pop_last(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + let mut key = KEY; + + c.bench_function(function_name!(), |b| { + b.iter_custom(|iters| { + for _ in 0..iters { + table.put(&key, &VALUE).unwrap(); + key.amount += 1; + } + + key = KEY; + + let start = Instant::now(); + for _ in 0..iters { + table.pop_last().unwrap(); + key.amount += 1; + } + start.elapsed() + }); + }); +} + +// TODO: waiting on PR 102 +// /// [`DatabaseRw::take`] +// #[named] +// fn take(c: &mut Criterion) { +// let (env, _tempdir) = tmp_concrete_env(); +// let env_inner = env.env_inner(); +// let tx_rw = env_inner.tx_rw().unwrap(); +// let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + +// let mut key = KEY; +// for _ in 0..100 { +// table.put(&key, &VALUE).unwrap(); +// key.amount += 1; +// } + +// c.bench_function(function_name!(), |b| { +// b.iter(|| { +// table.put(&KEY, &VALUE).unwrap(); +// let value: Output = black_box(table.take(&black_box(KEY)).unwrap()); +// }); +// }); +// } + +//---------------------------------------------------------------------------------------------------- DatabaseIter /// [`DatabaseRo::get_range`] #[named] fn get_range(c: &mut Criterion) { @@ -98,9 +492,9 @@ fn get_range(c: &mut Criterion) { }); } -/// [`DatabaseRw::delete`] +/// [`DatabaseRo::iter`] #[named] -fn delete(c: &mut Criterion) { +fn iter(c: &mut Criterion) { let (env, _tempdir) = tmp_concrete_env(); let env_inner = env.env_inner(); let tx_rw = env_inner.tx_rw().unwrap(); @@ -112,33 +506,78 @@ fn delete(c: &mut Criterion) { key.amount += 1; } + drop(table); + TxRw::commit(tx_rw).unwrap(); + + let tx_ro = env_inner.tx_ro().unwrap(); + let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap(); + c.bench_function(function_name!(), |b| { b.iter(|| { - table.put(&KEY, &VALUE).unwrap(); - table.delete(&black_box(KEY)).unwrap(); + let iter = black_box(table.iter()).unwrap(); + for result in iter { + let _: (PreRctOutputId, Output) = black_box(result.unwrap()); + } }); }); } -// TODO: waiting on PR 102 -// /// [`DatabaseRw::take`] -// #[named] -// fn take(c: &mut Criterion) { -// let (env, _tempdir) = tmp_concrete_env(); -// let env_inner = env.env_inner(); -// let tx_rw = env_inner.tx_rw().unwrap(); -// let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); +/// [`DatabaseRo::keys`] +#[named] +fn keys(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); -// let mut key = KEY; -// for _ in 0..100 { -// table.put(&key, &VALUE).unwrap(); -// key.amount += 1; -// } + let mut key = KEY; + for _ in 0..100 { + table.put(&key, &VALUE).unwrap(); + key.amount += 1; + } -// c.bench_function(function_name!(), |b| { -// b.iter(|| { -// table.put(&KEY, &VALUE).unwrap(); -// let value: Output = black_box(table.take(&black_box(KEY)).unwrap()); -// }); -// }); -// } + drop(table); + TxRw::commit(tx_rw).unwrap(); + + let tx_ro = env_inner.tx_ro().unwrap(); + let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + let keys = black_box(table.keys()).unwrap(); + for result in keys { + let _: PreRctOutputId = black_box(result.unwrap()); + } + }); + }); +} + +/// [`DatabaseRo::values`] +#[named] +fn values(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap(); + + let mut key = KEY; + for _ in 0..100 { + table.put(&key, &VALUE).unwrap(); + key.amount += 1; + } + + drop(table); + TxRw::commit(tx_rw).unwrap(); + + let tx_ro = env_inner.tx_ro().unwrap(); + let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + let values = black_box(table.values()).unwrap(); + for result in values { + let _: Output = black_box(result.unwrap()); + } + }); + }); +} diff --git a/database/benchmark/benches/env.rs b/database/benchmark/benches/env.rs index e0420f03..3a0c7880 100644 --- a/database/benchmark/benches/env.rs +++ b/database/benchmark/benches/env.rs @@ -15,7 +15,7 @@ use cuprate_database::{ use cuprate_database_benchmark::tmp_concrete_env; //---------------------------------------------------------------------------------------------------- Criterion -criterion_group!( +criterion_group! { benches, open, env_inner, @@ -26,7 +26,7 @@ criterion_group!( resize, current_map_size, disk_size_bytes, -); +} criterion_main!(benches); //---------------------------------------------------------------------------------------------------- Env benchmarks diff --git a/database/benchmark/benches/storable.rs b/database/benchmark/benches/storable.rs index d1b340d8..baa01b9f 100644 --- a/database/benchmark/benches/storable.rs +++ b/database/benchmark/benches/storable.rs @@ -11,13 +11,13 @@ use cuprate_database::{ }; //---------------------------------------------------------------------------------------------------- Criterion -criterion_group!( +criterion_group! { benches, pre_rct_output_id_as_bytes, pre_rct_output_id_from_bytes, output_as_bytes, output_from_bytes -); +} criterion_main!(benches); //---------------------------------------------------------------------------------------------------- Constants