diff --git a/database/README.md b/database/README.md index ba35d36d..e1335172 100644 --- a/database/README.md +++ b/database/README.md @@ -134,7 +134,7 @@ All backends follow the same file structure: | `types.rs` | Type aliases for long backend-specific types # Benchmarking -There is a standalone binary within `benchmark` that allows various testing and benchmarking on all the features of `cuprate-database`. +There is a `cargo bench` suite for `cuprate_database` within `benchmark/`. See [`benchmark/README.md`](benchmark/) for more info. diff --git a/database/benchmark/README.md b/database/benchmark/README.md index 0345482b..343f2031 100644 --- a/database/benchmark/README.md +++ b/database/benchmark/README.md @@ -1,48 +1,23 @@ # `cuprate-database-benchmark` -This is a standalone binary that allows testing/benchmarking `cuprate-database`. +This is a benchmarking suite that allows testing/benchmarking `cuprate-database` with [`criterion`](https://bheisler.github.io/criterion.rs/book/criterion_rs.html). + +For more information on `cargo bench` and `criterion`: +- https://doc.rust-lang.org/cargo/commands/cargo-bench.html +- https://bheisler.github.io/criterion.rs/book/criterion_rs.html -1. [Documentation](#documentation) +1. [Usage](#Usage) 1. [File Structure](#file-structure) - [`src/`](#src) - - [`src/ops`](#src-ops) - - [`src/service/`](#src-service) - - [`src/backend/`](#src-backend) -1. [Benchmarking](#benchmarking) -1. [Testing](#testing) + - [`benches/`](#benches) -# Documentation -In general, documentation for `database/` is split into 3: +# Usage +Ensure the system is as quiet as possible (no background tasks) before starting and during the benchmarks. -| Documentation location | Purpose | -|---------------------------|---------| -| `database/README.md` | High level design of `cuprate-database` -| `cuprate-database` | Practical usage documentation/warnings/notes/etc -| Source file `// comments` | Implementation-specific details (e.g, how many reader threads to spawn?) - -This README serves as the overview/design document. - -For actual practical usage, `cuprate-database`'s types and general usage are documented via standard Rust tooling. - -Run: +To start all benchmarks, run: ```bash -cargo doc --package cuprate-database --open +cargo bench --package cuprate-database-benchmarks ``` -at the root of the repo to open/read the documentation. - -If this documentation is too abstract, refer to any of the source files, they are heavily commented. There are many `// Regular comments` that explain more implementation specific details that aren't present here or in the docs. Use the file reference below to find what you're looking for. - -The code within `src/` is also littered with some `grep`-able comments containing some keywords: - -| Word | Meaning | -|-------------|---------| -| `INVARIANT` | This code makes an _assumption_ that must be upheld for correctness -| `SAFETY` | This `unsafe` code is okay, for `x,y,z` reasons -| `FIXME` | This code works but isn't ideal -| `HACK` | This code is a brittle workaround -| `PERF` | This code is weird for performance reasons -| `TODO` | This must be implemented; There should be 0 of these in production code -| `SOMEDAY` | This should be implemented... someday # File Structure A quick reference of the structure of the folders & files in `cuprate-database`. @@ -52,5 +27,21 @@ Note that `lib.rs/mod.rs` files are purely for re-exporting/visibility/lints, an ## `src/` The top-level `src/` files. +The actual `cuprate-database-benchmark` library crate is just used as a helper for the benchmarks within `benches/`. + | File | Purpose | |---------------------|---------| +| `helper.rs` | Helper functions + +## `benches/` +The actual benchmarks. + +Each file represents some logical benchmark grouping. + +| File | Purpose | +|-----------------------|---------| +| `db.rs` | `trait Database{Ro,Rw,Iter}` benchmarks +| `db_multi_thread.rs` | Same as `db.rs` but multi-threaded +| `env.rs` | `trait {Env, EnvInner, TxR{o,w}, Tables[Mut]}` benchmarks +| `env_multi_thread.rs` | Same as `env.rs` but multi-threaded +| `storable.rs` | `trait Storable` benchmarks \ No newline at end of file diff --git a/database/benchmark/benches/db_multi_thread.rs b/database/benchmark/benches/db_multi_thread.rs new file mode 100644 index 00000000..a4017672 --- /dev/null +++ b/database/benchmark/benches/db_multi_thread.rs @@ -0,0 +1,583 @@ +//! TODO: create multi-threaded benchmarks + +use std::time::Instant; + +//---------------------------------------------------------------------------------------------------- Import +use criterion::{black_box, criterion_group, criterion_main, Criterion}; + +use function_name::named; + +use cuprate_database::{ + tables::Outputs, + types::{Output, PreRctOutputId}, + DatabaseIter, DatabaseRo, DatabaseRw, Env, EnvInner, TxRw, +}; + +use cuprate_database_benchmark::tmp_concrete_env; + +//---------------------------------------------------------------------------------------------------- Criterion +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 +/// The (1st) key. +const KEY: PreRctOutputId = PreRctOutputId { + amount: 1, + amount_index: 123, +}; + +/// The expected value. +const VALUE: Output = Output { + key: [35; 32], + height: 45_761_798, + output_flags: 0, + tx_idx: 2_353_487, +}; + +//---------------------------------------------------------------------------------------------------- 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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&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) { + 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::(&tx_rw).unwrap(); + + let mut key = KEY; + + c.bench_function(function_name!(), |b| { + b.iter(|| { + table.put(black_box(&key), black_box(&VALUE)).unwrap(); + key.amount += 1; + }); + }); +} + +/// [`DatabaseRw::delete`] +#[named] +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::(&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.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::(&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::(&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::(&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) { + 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::(&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::(&tx_ro).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + let range = table.get_range(black_box(..)).unwrap(); + for result in range { + let _value: Output = black_box(result.unwrap()); + } + }); + }); +} + +/// [`DatabaseRo::iter`] +#[named] +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(); + let mut table = env_inner.open_db_rw::(&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::(&tx_ro).unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + let iter = black_box(table.iter()).unwrap(); + for result in iter { + let _: (PreRctOutputId, Output) = black_box(result.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::(&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::(&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::(&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::(&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 d7a72739..3a0c7880 100644 --- a/database/benchmark/benches/env.rs +++ b/database/benchmark/benches/env.rs @@ -50,7 +50,7 @@ fn env_inner(c: &mut Criterion) { c.bench_function(function_name!(), |b| { b.iter(|| { - let _ = black_box(env.env_inner()); + black_box(env.env_inner()); }); }); } diff --git a/database/benchmark/benches/env_multi_thread.rs b/database/benchmark/benches/env_multi_thread.rs new file mode 100644 index 00000000..8d0f6de3 --- /dev/null +++ b/database/benchmark/benches/env_multi_thread.rs @@ -0,0 +1,161 @@ +//! TODO: create multi-threaded benchmarks + +//---------------------------------------------------------------------------------------------------- Import +use criterion::{black_box, criterion_group, criterion_main, Criterion}; + +use function_name::named; + +use cuprate_database::{ + config::Config, + resize::{page_size, ResizeAlgorithm}, + tables::Outputs, + ConcreteEnv, Env, EnvInner, TxRo, TxRw, +}; + +use cuprate_database_benchmark::tmp_concrete_env; + +//---------------------------------------------------------------------------------------------------- Criterion +criterion_group! { + benches, + open, + env_inner, + tx_ro, + tx_rw, + open_tables, + open_tables_mut, + resize, + current_map_size, + disk_size_bytes, +} +criterion_main!(benches); + +//---------------------------------------------------------------------------------------------------- Env benchmarks +/// [`Env::open`]. +#[named] +fn open(c: &mut Criterion) { + let tempdir = tempfile::tempdir().unwrap(); + let config = Config::low_power(Some(tempdir.path().into())); + + c.bench_function(function_name!(), |b| { + b.iter_with_large_drop(|| { + ConcreteEnv::open(config.clone()).unwrap(); + }); + }); +} + +/// [`Env::env_inner`]. +#[named] +fn env_inner(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + black_box(env.env_inner()); + }); + }); +} + +/// Create and commit read-only transactions. +#[named] +fn tx_ro(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + let tx_ro = black_box(env_inner.tx_ro()).unwrap(); + TxRo::commit(black_box(tx_ro)).unwrap(); + }); + }); +} + +/// Create and commit read/write transactions. +#[named] +fn tx_rw(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + let tx_rw = black_box(env_inner.tx_rw()).unwrap(); + TxRw::commit(black_box(tx_rw)).unwrap(); + }); + }); +} + +/// Open all database tables in read-only mode. +#[named] +fn open_tables(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_ro = env_inner.tx_ro().unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + black_box(env_inner.open_db_ro::(&tx_ro)).unwrap(); + // env_inner.open_tables(&tx_ro).unwrap(); + // TODO: waiting on PR 102 + }); + }); +} + +/// Open all database tables in read/write mode. +#[named] +fn open_tables_mut(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw().unwrap(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + black_box(env_inner.open_db_rw::(&tx_rw)).unwrap(); + // env_inner.open_tables_mut(&mut tx_rw).unwrap(); + // TODO: waiting on PR 102 + }); + }); +} + +/// `Env` memory map resizes. +#[named] +fn resize(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + + // Resize by the OS page size. + let page_size = page_size(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + // This test is only valid for `Env`'s that need to resize manually. + if ConcreteEnv::MANUAL_RESIZE { + env.resize_map(black_box(Some(ResizeAlgorithm::FixedBytes(page_size)))); + } + }); + }); +} + +/// Access current memory map size of the database. +#[named] +fn current_map_size(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + // This test is only valid for `Env`'s that need to resize manually. + if ConcreteEnv::MANUAL_RESIZE { + black_box(env.current_map_size()); + } + }); + }); +} + +/// Access on-disk size of the database. +#[named] +fn disk_size_bytes(c: &mut Criterion) { + let (env, _tempdir) = tmp_concrete_env(); + + c.bench_function(function_name!(), |b| { + b.iter(|| { + black_box(env.disk_size_bytes()).unwrap(); + }); + }); +}