mirror of
https://github.com/hinto-janai/cuprate.git
synced 2025-01-10 21:04:59 +00:00
Compare commits
3 commits
7a94952e14
...
8ae208b9f0
Author | SHA1 | Date | |
---|---|---|---|
|
8ae208b9f0 | ||
|
0aa5f77c5e | ||
|
da3417f71f |
15 changed files with 403 additions and 1348 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -739,6 +739,19 @@ dependencies = [
|
||||||
name = "cuprate-constants"
|
name = "cuprate-constants"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cuprate-criterion-database"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"criterion",
|
||||||
|
"cuprate-blockchain",
|
||||||
|
"cuprate-database",
|
||||||
|
"cuprate-helper",
|
||||||
|
"function_name",
|
||||||
|
"rand",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cuprate-criterion-example"
|
name = "cuprate-criterion-example"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
|
|
@ -9,6 +9,7 @@ members = [
|
||||||
"benches/benchmark/example",
|
"benches/benchmark/example",
|
||||||
"benches/criterion/example",
|
"benches/criterion/example",
|
||||||
"benches/criterion/cuprate-json-rpc",
|
"benches/criterion/cuprate-json-rpc",
|
||||||
|
"benches/criterion/cuprate-database",
|
||||||
# Consensus
|
# Consensus
|
||||||
"consensus",
|
"consensus",
|
||||||
"consensus/fast-sync",
|
"consensus/fast-sync",
|
||||||
|
|
|
@ -20,6 +20,13 @@ use cfg_if::cfg_if;
|
||||||
/// 1. Copy + paste a `cfg_if` block
|
/// 1. Copy + paste a `cfg_if` block
|
||||||
/// 2. Change it to your benchmark's feature flag
|
/// 2. Change it to your benchmark's feature flag
|
||||||
/// 3. Change it to your benchmark's type
|
/// 3. Change it to your benchmark's type
|
||||||
|
#[allow(
|
||||||
|
clippy::allow_attributes,
|
||||||
|
unused_variables,
|
||||||
|
unused_mut,
|
||||||
|
unreachable_code,
|
||||||
|
reason = "clippy does not account for all cfg()s"
|
||||||
|
)]
|
||||||
fn main() {
|
fn main() {
|
||||||
log::init_logger();
|
log::init_logger();
|
||||||
|
|
||||||
|
@ -27,7 +34,8 @@ fn main() {
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(not(any(feature = "example")))] {
|
if #[cfg(not(any(feature = "example")))] {
|
||||||
compile_error!("No feature specified. Use `--features $BENCHMARK_FEATURE` when building.");
|
println!("No feature specified. Use `--features $BENCHMARK_FEATURE` when building.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,41 @@
|
||||||
[package]
|
[package]
|
||||||
name = "cuprate-database-benchmark"
|
name = "cuprate-criterion-database"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Benchmarking for Cuprate's database abstraction"
|
description = "Criterion benchmarking for cuprate-database"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
authors = ["hinto-janai"]
|
authors = ["hinto-janai"]
|
||||||
repository = "https://github.com/Cuprate/cuprate/tree/main/database/benchmark"
|
repository = "https://github.com/Cuprate/cuprate/tree/main/benches/criterion/cuprate-database"
|
||||||
keywords = ["cuprate", "database", "benchmark"]
|
keywords = ["cuprate", "database", "benchmark"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = ["heed"]
|
||||||
|
heed = ["cuprate-database/heed", "cuprate-blockchain/heed"]
|
||||||
|
redb = ["cuprate-database/redb", "cuprate-blockchain/redb"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
# FIXME:
|
||||||
|
# Some crates/features that are unused here but
|
||||||
|
# needed in other crates are pulled in, see:
|
||||||
|
# - <https://github.com/Cuprate/cuprate/issues/325>
|
||||||
|
#
|
||||||
|
# Remove:
|
||||||
|
# - rand
|
||||||
|
# - cuprate-blockchain/asynch
|
||||||
|
# - cuprate-blockchain/tx
|
||||||
|
|
||||||
criterion = { workspace = true }
|
criterion = { workspace = true }
|
||||||
cuprate-database = { path = "../", features = ["default"] }
|
cuprate-database = { path = "../../../storage/database" }
|
||||||
cuprate-helper = { path = "../../helper", features = ["fs", "thread"] }
|
cuprate-blockchain = { path = "../../../storage/blockchain", features = ["service"] }
|
||||||
# cuprate-types = { path = "../../types", features = ["service"] }
|
cuprate-helper = { path = "../../../helper", features = ["asynch", "fs", "thread", "tx"] }
|
||||||
function_name = { version = "0.3.0" }
|
|
||||||
tempfile = { version = "3.10.0" }
|
function_name = { workspace = true }
|
||||||
|
tempfile = { workspace = true }
|
||||||
|
rand = { workspace = true, features = ["std", "std_rng"] }
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "main"
|
name = "main"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
|
@ -1,61 +1,61 @@
|
||||||
//! `trait Database{Ro,Rw,Iter}` benchmarks.
|
//! Database operations.
|
||||||
|
//!
|
||||||
|
//! This module tests the functions from:
|
||||||
|
//! - [`cuprate_database::DatabaseRo`]
|
||||||
|
//! - [`cuprate_database::DatabaseRw`]
|
||||||
|
//! - [`cuprate_database::DatabaseIter`]
|
||||||
|
|
||||||
|
#![allow(unused_crate_dependencies, unused_attributes)]
|
||||||
|
#![expect(clippy::significant_drop_tightening)]
|
||||||
|
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Import
|
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
|
|
||||||
use function_name::named;
|
use function_name::named;
|
||||||
|
|
||||||
use cuprate_database::{
|
use cuprate_blockchain::{
|
||||||
tables::Outputs,
|
tables::Outputs,
|
||||||
types::{Output, PreRctOutputId},
|
types::{Output, PreRctOutputId},
|
||||||
DatabaseIter, DatabaseRo, DatabaseRw, Env, EnvInner, TxRw,
|
|
||||||
};
|
};
|
||||||
|
use cuprate_database::{DatabaseIter, DatabaseRo, DatabaseRw, Env, EnvInner};
|
||||||
|
|
||||||
use cuprate_database_benchmark::tmp_env;
|
use cuprate_criterion_database::{TmpEnv, KEY, VALUE};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Criterion
|
|
||||||
criterion_group! {
|
criterion_group! {
|
||||||
benches,
|
name = benches;
|
||||||
|
config = Criterion::default();
|
||||||
|
targets =
|
||||||
|
// `DatabaseRo`
|
||||||
ro_get,
|
ro_get,
|
||||||
ro_len,
|
ro_len,
|
||||||
ro_first,
|
ro_first,
|
||||||
ro_last,
|
ro_last,
|
||||||
ro_is_empty,
|
ro_is_empty,
|
||||||
ro_contains,
|
ro_contains,
|
||||||
|
|
||||||
|
// `DatabaseRo` with a `TxRw`
|
||||||
rw_get,
|
rw_get,
|
||||||
rw_len,
|
rw_len,
|
||||||
rw_first,
|
rw_first,
|
||||||
rw_last,
|
rw_last,
|
||||||
rw_is_empty,
|
rw_is_empty,
|
||||||
rw_contains,
|
rw_contains,
|
||||||
put,
|
|
||||||
delete,
|
// `DatabaseIter`
|
||||||
pop_first,
|
|
||||||
pop_last,
|
|
||||||
get_range,
|
get_range,
|
||||||
iter,
|
iter,
|
||||||
keys,
|
keys,
|
||||||
values,
|
values,
|
||||||
|
|
||||||
|
// `DatabaseRw`
|
||||||
|
put,
|
||||||
|
delete,
|
||||||
|
pop_first,
|
||||||
|
pop_last,
|
||||||
|
take,
|
||||||
}
|
}
|
||||||
criterion_main!(benches);
|
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
|
//---------------------------------------------------------------------------------------------------- DatabaseRo
|
||||||
// Read-only table operations.
|
// Read-only table operations.
|
||||||
// This uses `TxRw + TablesMut` briefly to insert values, then
|
// This uses `TxRw + TablesMut` briefly to insert values, then
|
||||||
|
@ -66,21 +66,14 @@ const VALUE: Output = Output {
|
||||||
/// [`DatabaseRo::get`]
|
/// [`DatabaseRo::get`]
|
||||||
#[named]
|
#[named]
|
||||||
fn ro_get(c: &mut Criterion) {
|
fn ro_get(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new().with_key_value();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.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 tx_ro = env_inner.tx_ro().unwrap();
|
||||||
let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let _value: Output = table.get(black_box(&KEY)).unwrap();
|
let _: Output = table.get(black_box(&KEY)).unwrap();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -88,15 +81,8 @@ fn ro_get(c: &mut Criterion) {
|
||||||
/// [`DatabaseRo::len`]
|
/// [`DatabaseRo::len`]
|
||||||
#[named]
|
#[named]
|
||||||
fn ro_len(c: &mut Criterion) {
|
fn ro_len(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new().with_key_value();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.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 tx_ro = env_inner.tx_ro().unwrap();
|
||||||
let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
||||||
|
|
||||||
|
@ -110,15 +96,8 @@ fn ro_len(c: &mut Criterion) {
|
||||||
/// [`DatabaseRo::first`]
|
/// [`DatabaseRo::first`]
|
||||||
#[named]
|
#[named]
|
||||||
fn ro_first(c: &mut Criterion) {
|
fn ro_first(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new().with_key_value();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.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 tx_ro = env_inner.tx_ro().unwrap();
|
||||||
let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
||||||
|
|
||||||
|
@ -132,15 +111,8 @@ fn ro_first(c: &mut Criterion) {
|
||||||
/// [`DatabaseRo::last`]
|
/// [`DatabaseRo::last`]
|
||||||
#[named]
|
#[named]
|
||||||
fn ro_last(c: &mut Criterion) {
|
fn ro_last(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new().with_key_value();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.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 tx_ro = env_inner.tx_ro().unwrap();
|
||||||
let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
||||||
|
|
||||||
|
@ -154,15 +126,8 @@ fn ro_last(c: &mut Criterion) {
|
||||||
/// [`DatabaseRo::is_empty`]
|
/// [`DatabaseRo::is_empty`]
|
||||||
#[named]
|
#[named]
|
||||||
fn ro_is_empty(c: &mut Criterion) {
|
fn ro_is_empty(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new().with_key_value();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.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 tx_ro = env_inner.tx_ro().unwrap();
|
||||||
let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
||||||
|
|
||||||
|
@ -176,15 +141,8 @@ fn ro_is_empty(c: &mut Criterion) {
|
||||||
/// [`DatabaseRo::contains`]
|
/// [`DatabaseRo::contains`]
|
||||||
#[named]
|
#[named]
|
||||||
fn ro_contains(c: &mut Criterion) {
|
fn ro_contains(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new().with_key_value();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.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 tx_ro = env_inner.tx_ro().unwrap();
|
||||||
let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
let table = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
||||||
|
|
||||||
|
@ -195,45 +153,31 @@ fn ro_contains(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- DatabaseRo (using TxRw)
|
//---------------------------------------------------------------------------------------------------- DatabaseRo (TxRw)
|
||||||
// These are the same benchmarks as above, but it uses a
|
// These are the same benchmarks as above, but it uses a
|
||||||
// `TxRw` and a `TablesMut` instead to ensure our read/write tables
|
// `TxRw` and a `TablesMut` instead to ensure our read/write tables
|
||||||
// using read operations perform the same as normal read-only tables.
|
// using read operations perform the same as normal read-only tables.
|
||||||
|
|
||||||
/// [`DatabaseRo::get`]
|
/// [`DatabaseRw::get`]
|
||||||
#[named]
|
#[named]
|
||||||
fn rw_get(c: &mut Criterion) {
|
fn rw_get(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new().with_key_value();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.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 tx_rw = env_inner.tx_rw().unwrap();
|
||||||
let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let _value: Output = table.get(black_box(&KEY)).unwrap();
|
let _: Output = table.get(black_box(&KEY)).unwrap();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [`DatabaseRo::len`]
|
/// [`DatabaseRw::len`]
|
||||||
#[named]
|
#[named]
|
||||||
fn rw_len(c: &mut Criterion) {
|
fn rw_len(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new().with_key_value();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.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 tx_rw = env_inner.tx_rw().unwrap();
|
||||||
let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
||||||
|
|
||||||
|
@ -244,18 +188,11 @@ fn rw_len(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [`DatabaseRo::first`]
|
/// [`DatabaseRw::first`]
|
||||||
#[named]
|
#[named]
|
||||||
fn rw_first(c: &mut Criterion) {
|
fn rw_first(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new().with_key_value();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.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 tx_rw = env_inner.tx_rw().unwrap();
|
||||||
let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
||||||
|
|
||||||
|
@ -266,18 +203,11 @@ fn rw_first(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [`DatabaseRo::last`]
|
/// [`DatabaseRw::last`]
|
||||||
#[named]
|
#[named]
|
||||||
fn rw_last(c: &mut Criterion) {
|
fn rw_last(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new().with_key_value();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.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 tx_rw = env_inner.tx_rw().unwrap();
|
||||||
let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
||||||
|
|
||||||
|
@ -288,18 +218,11 @@ fn rw_last(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [`DatabaseRo::is_empty`]
|
/// [`DatabaseRw::is_empty`]
|
||||||
#[named]
|
#[named]
|
||||||
fn rw_is_empty(c: &mut Criterion) {
|
fn rw_is_empty(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new().with_key_value();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.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 tx_rw = env_inner.tx_rw().unwrap();
|
||||||
let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
||||||
|
|
||||||
|
@ -310,18 +233,11 @@ fn rw_is_empty(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [`DatabaseRo::contains`]
|
/// [`DatabaseRw::contains`]
|
||||||
#[named]
|
#[named]
|
||||||
fn rw_contains(c: &mut Criterion) {
|
fn rw_contains(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new().with_key_value();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.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 tx_rw = env_inner.tx_rw().unwrap();
|
||||||
let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
||||||
|
|
||||||
|
@ -332,12 +248,85 @@ fn rw_contains(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------- DatabaseIter
|
||||||
|
/// [`DatabaseIter::get_range`]
|
||||||
|
#[named]
|
||||||
|
fn get_range(c: &mut Criterion) {
|
||||||
|
let env = TmpEnv::new().with_key_value_100();
|
||||||
|
let env_inner = env.env.env_inner();
|
||||||
|
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 range = table.get_range(black_box(..)).unwrap();
|
||||||
|
for result in range {
|
||||||
|
let _: Output = black_box(result.unwrap());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [`DatabaseIter::iter`]
|
||||||
|
#[named]
|
||||||
|
fn iter(c: &mut Criterion) {
|
||||||
|
let env = TmpEnv::new().with_key_value_100();
|
||||||
|
let env_inner = env.env.env_inner();
|
||||||
|
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 iter = black_box(table.iter()).unwrap();
|
||||||
|
for result in iter {
|
||||||
|
let _: (PreRctOutputId, Output) = black_box(result.unwrap());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [`DatabaseIter::keys`]
|
||||||
|
#[named]
|
||||||
|
fn keys(c: &mut Criterion) {
|
||||||
|
let env = TmpEnv::new().with_key_value_100();
|
||||||
|
let env_inner = env.env.env_inner();
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [`DatabaseIter::values`]
|
||||||
|
#[named]
|
||||||
|
fn values(c: &mut Criterion) {
|
||||||
|
let env = TmpEnv::new().with_key_value_100();
|
||||||
|
let env_inner = env.env.env_inner();
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- DatabaseRw
|
//---------------------------------------------------------------------------------------------------- DatabaseRw
|
||||||
/// [`DatabaseRw::put`]
|
/// [`DatabaseRw::put`]
|
||||||
#[named]
|
#[named]
|
||||||
fn put(c: &mut Criterion) {
|
fn put(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.env.env_inner();
|
||||||
let tx_rw = env_inner.tx_rw().unwrap();
|
let tx_rw = env_inner.tx_rw().unwrap();
|
||||||
let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
||||||
|
|
||||||
|
@ -354,8 +343,8 @@ fn put(c: &mut Criterion) {
|
||||||
/// [`DatabaseRw::delete`]
|
/// [`DatabaseRw::delete`]
|
||||||
#[named]
|
#[named]
|
||||||
fn delete(c: &mut Criterion) {
|
fn delete(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.env.env_inner();
|
||||||
let tx_rw = env_inner.tx_rw().unwrap();
|
let tx_rw = env_inner.tx_rw().unwrap();
|
||||||
let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
||||||
|
|
||||||
|
@ -383,8 +372,8 @@ fn delete(c: &mut Criterion) {
|
||||||
/// [`DatabaseRw::pop_first`]
|
/// [`DatabaseRw::pop_first`]
|
||||||
#[named]
|
#[named]
|
||||||
fn pop_first(c: &mut Criterion) {
|
fn pop_first(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.env.env_inner();
|
||||||
let tx_rw = env_inner.tx_rw().unwrap();
|
let tx_rw = env_inner.tx_rw().unwrap();
|
||||||
let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
||||||
|
|
||||||
|
@ -412,8 +401,8 @@ fn pop_first(c: &mut Criterion) {
|
||||||
/// [`DatabaseRw::pop_last`]
|
/// [`DatabaseRw::pop_last`]
|
||||||
#[named]
|
#[named]
|
||||||
fn pop_last(c: &mut Criterion) {
|
fn pop_last(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.env.env_inner();
|
||||||
let tx_rw = env_inner.tx_rw().unwrap();
|
let tx_rw = env_inner.tx_rw().unwrap();
|
||||||
let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
||||||
|
|
||||||
|
@ -438,146 +427,18 @@ fn pop_last(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: waiting on PR 102
|
/// [`DatabaseRw::take`]
|
||||||
// /// [`DatabaseRw::take`]
|
|
||||||
// #[named]
|
|
||||||
// fn take(c: &mut Criterion) {
|
|
||||||
// let (env, _tempdir) = tmp_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]
|
#[named]
|
||||||
fn get_range(c: &mut Criterion) {
|
fn take(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.env.env_inner();
|
||||||
let tx_rw = env_inner.tx_rw().unwrap();
|
let tx_rw = env_inner.tx_rw().unwrap();
|
||||||
let mut table = env_inner.open_db_rw::<Outputs>(&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| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let range = table.get_range(black_box(..)).unwrap();
|
table.put(&KEY, &VALUE).unwrap();
|
||||||
for result in range {
|
let _: Output = black_box(table.take(&black_box(KEY)).unwrap());
|
||||||
let _value: Output = black_box(result.unwrap());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// [`DatabaseRo::iter`]
|
|
||||||
#[named]
|
|
||||||
fn iter(c: &mut Criterion) {
|
|
||||||
let (env, _tempdir) = tmp_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 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_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 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_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());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,584 +0,0 @@
|
||||||
//! Same as `db.rs` but multi-threaded.
|
|
||||||
//! 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_env_all_threads;
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- 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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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) {
|
|
||||||
let (env, _tempdir) = tmp_env_all_threads();
|
|
||||||
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(|| {
|
|
||||||
table.put(black_box(&key), black_box(&VALUE)).unwrap();
|
|
||||||
key.amount += 1;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// [`DatabaseRw::delete`]
|
|
||||||
#[named]
|
|
||||||
fn delete(c: &mut Criterion) {
|
|
||||||
let (env, _tempdir) = tmp_env_all_threads();
|
|
||||||
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.delete(&key).unwrap();
|
|
||||||
key.amount += 1;
|
|
||||||
}
|
|
||||||
start.elapsed()
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// [`DatabaseRw::pop_first`]
|
|
||||||
#[named]
|
|
||||||
fn pop_first(c: &mut Criterion) {
|
|
||||||
let (env, _tempdir) = tmp_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
// 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) {
|
|
||||||
let (env, _tempdir) = tmp_env_all_threads();
|
|
||||||
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 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_env_all_threads();
|
|
||||||
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 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_env_all_threads();
|
|
||||||
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 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_env_all_threads();
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,65 +1,75 @@
|
||||||
//! `trait {Env, EnvInner, TxR{o,w}, Tables[Mut]}` benchmarks.
|
//! [`Env`] benchmarks.
|
||||||
|
|
||||||
|
#![allow(unused_crate_dependencies, unused_attributes)]
|
||||||
|
#![expect(clippy::significant_drop_tightening)]
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Import
|
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
|
|
||||||
use function_name::named;
|
use function_name::named;
|
||||||
|
|
||||||
|
use cuprate_blockchain::tables::Outputs;
|
||||||
use cuprate_database::{
|
use cuprate_database::{
|
||||||
config::Config,
|
resize::{ResizeAlgorithm, PAGE_SIZE},
|
||||||
resize::{page_size, ResizeAlgorithm},
|
|
||||||
tables::Outputs,
|
|
||||||
ConcreteEnv, Env, EnvInner, TxRo, TxRw,
|
ConcreteEnv, Env, EnvInner, TxRo, TxRw,
|
||||||
};
|
};
|
||||||
|
|
||||||
use cuprate_database_benchmark::tmp_env;
|
use cuprate_criterion_database::TmpEnv;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Criterion
|
|
||||||
criterion_group! {
|
criterion_group! {
|
||||||
benches,
|
name = benches;
|
||||||
open,
|
config = Criterion::default();
|
||||||
|
targets =
|
||||||
|
// open,
|
||||||
env_inner,
|
env_inner,
|
||||||
tx_ro,
|
tx_ro,
|
||||||
tx_rw,
|
tx_rw,
|
||||||
open_tables,
|
open_db_ro,
|
||||||
open_tables_mut,
|
open_db_rw,
|
||||||
|
create_db,
|
||||||
resize,
|
resize,
|
||||||
current_map_size,
|
current_map_size,
|
||||||
disk_size_bytes,
|
disk_size_bytes,
|
||||||
}
|
}
|
||||||
criterion_main!(benches);
|
criterion_main!(benches);
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Env benchmarks
|
// FIXME: This function is hard to time due to:
|
||||||
/// [`Env::open`].
|
// - heed errors
|
||||||
#[named]
|
// - "too many open files" errors
|
||||||
fn open(c: &mut Criterion) {
|
//
|
||||||
let tempdir = tempfile::tempdir().unwrap();
|
// /// [`Env::open`].
|
||||||
let config = Config::low_power(Some(tempdir.path().into()));
|
// #[named]
|
||||||
|
// fn open(c: &mut Criterion) {
|
||||||
c.bench_function(function_name!(), |b| {
|
// c.bench_function(function_name!(), |b| {
|
||||||
b.iter_with_large_drop(|| {
|
// b.iter_custom(|_| {
|
||||||
ConcreteEnv::open(config.clone()).unwrap();
|
// let tempdir = tempfile::tempdir().unwrap();
|
||||||
});
|
// let config = ConfigBuilder::new(tempdir.path().to_path_buf().into()).build();
|
||||||
});
|
//
|
||||||
}
|
// let now = std::time::Instant::now();
|
||||||
|
// ConcreteEnv::open(config).unwrap();
|
||||||
|
// let elapsed = now.elapsed();
|
||||||
|
//
|
||||||
|
// tempdir.close().unwrap();
|
||||||
|
// elapsed
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
/// [`Env::env_inner`].
|
/// [`Env::env_inner`].
|
||||||
#[named]
|
#[named]
|
||||||
fn env_inner(c: &mut Criterion) {
|
fn env_inner(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new();
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
black_box(env.env_inner());
|
drop(black_box(env.env.env_inner()));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create and commit read-only transactions.
|
/// [`EnvInner::tx_ro`].
|
||||||
#[named]
|
#[named]
|
||||||
fn tx_ro(c: &mut Criterion) {
|
fn tx_ro(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.env.env_inner();
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
@ -69,11 +79,11 @@ fn tx_ro(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create and commit read/write transactions.
|
/// [`EnvInner::tx_rw`].
|
||||||
#[named]
|
#[named]
|
||||||
fn tx_rw(c: &mut Criterion) {
|
fn tx_rw(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.env.env_inner();
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
@ -83,79 +93,91 @@ fn tx_rw(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open all database tables in read-only mode.
|
/// [`EnvInner::open_db_ro`].
|
||||||
#[named]
|
#[named]
|
||||||
fn open_tables(c: &mut Criterion) {
|
fn open_db_ro(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
// `with_key_value()` creates the `Outputs`
|
||||||
let env_inner = env.env_inner();
|
// table so the `open_db_ro` below doesn't panic.
|
||||||
|
let env = TmpEnv::new().with_key_value();
|
||||||
|
let env_inner = env.env.env_inner();
|
||||||
let tx_ro = env_inner.tx_ro().unwrap();
|
let tx_ro = env_inner.tx_ro().unwrap();
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
black_box(env_inner.open_db_ro::<Outputs>(&tx_ro)).unwrap();
|
env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
|
||||||
// env_inner.open_tables(&tx_ro).unwrap();
|
|
||||||
// TODO: waiting on PR 102
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open all database tables in read/write mode.
|
/// [`EnvInner::open_db_rw`].
|
||||||
#[named]
|
#[named]
|
||||||
fn open_tables_mut(c: &mut Criterion) {
|
fn open_db_rw(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new();
|
||||||
let env_inner = env.env_inner();
|
let env_inner = env.env.env_inner();
|
||||||
let tx_rw = env_inner.tx_rw().unwrap();
|
let tx_rw = env_inner.tx_rw().unwrap();
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
black_box(env_inner.open_db_rw::<Outputs>(&tx_rw)).unwrap();
|
env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
|
||||||
// env_inner.open_tables_mut(&mut tx_rw).unwrap();
|
|
||||||
// TODO: waiting on PR 102
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Env` memory map resizes.
|
/// [`EnvInner::create_db`].
|
||||||
|
#[named]
|
||||||
|
fn create_db(c: &mut Criterion) {
|
||||||
|
let env = TmpEnv::new();
|
||||||
|
let env_inner = env.env.env_inner();
|
||||||
|
let tx_rw = env_inner.tx_rw().unwrap();
|
||||||
|
|
||||||
|
c.bench_function(function_name!(), |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
env_inner.create_db::<Outputs>(&tx_rw).unwrap();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [`Env::resize`].
|
||||||
#[named]
|
#[named]
|
||||||
fn resize(c: &mut Criterion) {
|
fn resize(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new();
|
||||||
|
|
||||||
// Resize by the OS page size.
|
// Resize env.by the OS page size.
|
||||||
let page_size = page_size();
|
let resize = Some(ResizeAlgorithm::FixedBytes(*PAGE_SIZE));
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
// This test is only valid for `Env`'s that need to resize manually.
|
// This test is only valid for `Env`'s that need to resize manually.
|
||||||
if ConcreteEnv::MANUAL_RESIZE {
|
if ConcreteEnv::MANUAL_RESIZE {
|
||||||
env.resize_map(black_box(Some(ResizeAlgorithm::FixedBytes(page_size))));
|
env.env.resize_map(resize);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access current memory map size of the database.
|
/// [`Env::current_map_size`].
|
||||||
#[named]
|
#[named]
|
||||||
fn current_map_size(c: &mut Criterion) {
|
fn current_map_size(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new();
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
// This test is only valid for `Env`'s that need to resize manually.
|
// This test is only valid for `Env`'s that need to resize manually.
|
||||||
if ConcreteEnv::MANUAL_RESIZE {
|
if ConcreteEnv::MANUAL_RESIZE {
|
||||||
black_box(env.current_map_size());
|
black_box(env.env.current_map_size());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access on-disk size of the database.
|
/// [`Env::disk_size_bytes`].
|
||||||
#[named]
|
#[named]
|
||||||
fn disk_size_bytes(c: &mut Criterion) {
|
fn disk_size_bytes(c: &mut Criterion) {
|
||||||
let (env, _tempdir) = tmp_env();
|
let env = TmpEnv::new();
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
black_box(env.disk_size_bytes()).unwrap();
|
black_box(env.env.disk_size_bytes()).unwrap();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,162 +0,0 @@
|
||||||
//! Same as `env.rs` but multi-threaded.
|
|
||||||
//! 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_env_all_threads;
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- 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_env_all_threads();
|
|
||||||
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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_env_all_threads();
|
|
||||||
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::<Outputs>(&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_env_all_threads();
|
|
||||||
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::<Outputs>(&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_env_all_threads();
|
|
||||||
|
|
||||||
// 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_env_all_threads();
|
|
||||||
|
|
||||||
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_env_all_threads();
|
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
|
||||||
b.iter(|| {
|
|
||||||
black_box(env.disk_size_bytes()).unwrap();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,84 +1,4 @@
|
||||||
//! TODO
|
#![expect(unused_crate_dependencies)]
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Lints
|
|
||||||
// Forbid lints.
|
|
||||||
// Our code, and code generated (e.g macros) cannot overrule these.
|
|
||||||
#![forbid(
|
|
||||||
// `unsafe` is allowed but it _must_ be
|
|
||||||
// commented with `SAFETY: reason`.
|
|
||||||
clippy::undocumented_unsafe_blocks,
|
|
||||||
|
|
||||||
// Never.
|
|
||||||
unused_unsafe,
|
|
||||||
redundant_semicolons,
|
|
||||||
unused_allocation,
|
|
||||||
coherence_leak_check,
|
|
||||||
while_true,
|
|
||||||
clippy::missing_docs_in_private_items,
|
|
||||||
|
|
||||||
// Maybe can be put into `#[deny]`.
|
|
||||||
unconditional_recursion,
|
|
||||||
for_loops_over_fallibles,
|
|
||||||
unused_braces,
|
|
||||||
unused_doc_comments,
|
|
||||||
unused_labels,
|
|
||||||
keyword_idents,
|
|
||||||
non_ascii_idents,
|
|
||||||
variant_size_differences,
|
|
||||||
single_use_lifetimes,
|
|
||||||
|
|
||||||
// Probably can be put into `#[deny]`.
|
|
||||||
future_incompatible,
|
|
||||||
let_underscore,
|
|
||||||
break_with_label_and_loop,
|
|
||||||
duplicate_macro_attributes,
|
|
||||||
exported_private_dependencies,
|
|
||||||
large_assignments,
|
|
||||||
overlapping_range_endpoints,
|
|
||||||
semicolon_in_expressions_from_macros,
|
|
||||||
noop_method_call,
|
|
||||||
unreachable_pub,
|
|
||||||
)]
|
|
||||||
// Deny lints.
|
|
||||||
// Some of these are `#[allow]`'ed on a per-case basis.
|
|
||||||
#![deny(
|
|
||||||
clippy::all,
|
|
||||||
clippy::correctness,
|
|
||||||
clippy::suspicious,
|
|
||||||
clippy::style,
|
|
||||||
clippy::complexity,
|
|
||||||
clippy::perf,
|
|
||||||
clippy::pedantic,
|
|
||||||
clippy::nursery,
|
|
||||||
clippy::cargo,
|
|
||||||
unused_mut,
|
|
||||||
missing_docs,
|
|
||||||
deprecated,
|
|
||||||
unused_comparisons,
|
|
||||||
nonstandard_style
|
|
||||||
)]
|
|
||||||
#![allow(unreachable_code, unused_variables, dead_code, unused_imports)] // TODO: remove
|
|
||||||
#![allow(
|
|
||||||
// FIXME: this lint affects crates outside of
|
|
||||||
// `database/` for some reason, allow for now.
|
|
||||||
clippy::cargo_common_metadata,
|
|
||||||
|
|
||||||
// FIXME: adding `#[must_use]` onto everything
|
|
||||||
// might just be more annoying than useful...
|
|
||||||
// although it is sometimes nice.
|
|
||||||
clippy::must_use_candidate,
|
|
||||||
|
|
||||||
// TODO: should be removed after all `todo!()`'s are gone.
|
|
||||||
clippy::diverging_sub_expression,
|
|
||||||
|
|
||||||
clippy::module_name_repetitions,
|
|
||||||
clippy::module_inception,
|
|
||||||
clippy::redundant_pub_crate,
|
|
||||||
clippy::option_if_let_else,
|
|
||||||
clippy::significant_drop_tightening,
|
|
||||||
)]
|
|
||||||
// Allow some lints when running in debug mode.
|
|
||||||
#![cfg_attr(debug_assertions, allow(clippy::todo, clippy::multiple_crate_versions))]
|
|
||||||
|
|
||||||
mod db;
|
mod db;
|
||||||
mod env;
|
mod env;
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
//! `cuprate_database::service` 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_env_all_threads;
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Criterion
|
|
||||||
criterion_group! {
|
|
||||||
benches,
|
|
||||||
}
|
|
||||||
criterion_main!(benches);
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Benchmarks
|
|
||||||
|
|
||||||
// TODO
|
|
|
@ -1,18 +1,19 @@
|
||||||
//! `trait Storable` benchmarks.
|
//! [`Storable`] benchmarks.
|
||||||
|
|
||||||
|
#![allow(unused_crate_dependencies, unused_attributes)]
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Import
|
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
|
|
||||||
use function_name::named;
|
use function_name::named;
|
||||||
|
|
||||||
use cuprate_database::{
|
use cuprate_blockchain::types::{Output, PreRctOutputId};
|
||||||
types::{Output, PreRctOutputId},
|
use cuprate_database::Storable;
|
||||||
Storable,
|
|
||||||
};
|
use cuprate_criterion_database::{KEY, VALUE};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Criterion
|
|
||||||
criterion_group! {
|
criterion_group! {
|
||||||
benches,
|
name = benches;
|
||||||
|
config = Criterion::default();
|
||||||
|
targets =
|
||||||
pre_rct_output_id_as_bytes,
|
pre_rct_output_id_as_bytes,
|
||||||
pre_rct_output_id_from_bytes,
|
pre_rct_output_id_from_bytes,
|
||||||
output_as_bytes,
|
output_as_bytes,
|
||||||
|
@ -20,28 +21,12 @@ criterion_group! {
|
||||||
}
|
}
|
||||||
criterion_main!(benches);
|
criterion_main!(benches);
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Constants
|
|
||||||
/// 16 bytes.
|
|
||||||
const PRE_RCT_OUTPUT_ID: PreRctOutputId = PreRctOutputId {
|
|
||||||
amount: 1,
|
|
||||||
amount_index: 123,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// 48 bytes.
|
|
||||||
const OUTPUT: Output = Output {
|
|
||||||
key: [35; 32],
|
|
||||||
height: 45_761_798,
|
|
||||||
output_flags: 0,
|
|
||||||
tx_idx: 2_353_487,
|
|
||||||
};
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Storable benchmarks
|
|
||||||
/// [`PreRctOutputId`] cast as bytes.
|
/// [`PreRctOutputId`] cast as bytes.
|
||||||
#[named]
|
#[named]
|
||||||
fn pre_rct_output_id_as_bytes(c: &mut Criterion) {
|
fn pre_rct_output_id_as_bytes(c: &mut Criterion) {
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
black_box(Storable::as_bytes(black_box(&PRE_RCT_OUTPUT_ID)));
|
black_box(Storable::as_bytes(black_box(&KEY)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -49,7 +34,7 @@ fn pre_rct_output_id_as_bytes(c: &mut Criterion) {
|
||||||
/// [`PreRctOutputId`] cast from bytes.
|
/// [`PreRctOutputId`] cast from bytes.
|
||||||
#[named]
|
#[named]
|
||||||
fn pre_rct_output_id_from_bytes(c: &mut Criterion) {
|
fn pre_rct_output_id_from_bytes(c: &mut Criterion) {
|
||||||
let bytes = Storable::as_bytes(&PRE_RCT_OUTPUT_ID);
|
let bytes = Storable::as_bytes(&KEY);
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
@ -63,7 +48,7 @@ fn pre_rct_output_id_from_bytes(c: &mut Criterion) {
|
||||||
fn output_as_bytes(c: &mut Criterion) {
|
fn output_as_bytes(c: &mut Criterion) {
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
black_box(Storable::as_bytes(black_box(&OUTPUT)));
|
black_box(Storable::as_bytes(black_box(&VALUE)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -71,7 +56,7 @@ fn output_as_bytes(c: &mut Criterion) {
|
||||||
/// [`Output`] cast from bytes.
|
/// [`Output`] cast from bytes.
|
||||||
#[named]
|
#[named]
|
||||||
fn output_from_bytes(c: &mut Criterion) {
|
fn output_from_bytes(c: &mut Criterion) {
|
||||||
let bytes = Storable::as_bytes(&OUTPUT);
|
let bytes = Storable::as_bytes(&VALUE);
|
||||||
|
|
||||||
c.bench_function(function_name!(), |b| {
|
c.bench_function(function_name!(), |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
|
17
benches/criterion/cuprate-database/src/constants.rs
Normal file
17
benches/criterion/cuprate-database/src/constants.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
//! General constants.
|
||||||
|
|
||||||
|
use cuprate_blockchain::types::{Output, OutputFlags, PreRctOutputId};
|
||||||
|
|
||||||
|
/// The (1st) key.
|
||||||
|
pub const KEY: PreRctOutputId = PreRctOutputId {
|
||||||
|
amount: 1,
|
||||||
|
amount_index: 123,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The expected value.
|
||||||
|
pub const VALUE: Output = Output {
|
||||||
|
key: [35; 32],
|
||||||
|
height: 45_761_798,
|
||||||
|
output_flags: OutputFlags::empty(),
|
||||||
|
tx_idx: 2_353_487,
|
||||||
|
};
|
|
@ -1,30 +0,0 @@
|
||||||
//! TODO
|
|
||||||
|
|
||||||
// TODO: set-up env based on config
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Import
|
|
||||||
use cuprate_database::{config::Config, ConcreteEnv, Env};
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Tests
|
|
||||||
/// Create an `Env` in a temporarily directory.
|
|
||||||
/// The directory is automatically removed after the `TempDir` is dropped.
|
|
||||||
///
|
|
||||||
/// TODO: changing this to `-> impl Env` causes lifetime errors...
|
|
||||||
#[allow(clippy::missing_panics_doc)]
|
|
||||||
pub fn tmp_env() -> (ConcreteEnv, tempfile::TempDir) {
|
|
||||||
let tempdir = tempfile::tempdir().unwrap();
|
|
||||||
let config = Config::low_power(Some(tempdir.path().into()));
|
|
||||||
let env = ConcreteEnv::open(config).unwrap();
|
|
||||||
|
|
||||||
(env, tempdir)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Same as [`tmp_env`] but uses all system threads.
|
|
||||||
#[allow(clippy::missing_panics_doc)]
|
|
||||||
pub fn tmp_env_all_threads() -> (ConcreteEnv, tempfile::TempDir) {
|
|
||||||
let tempdir = tempfile::tempdir().unwrap();
|
|
||||||
let config = Config::fast(Some(tempdir.path().into()));
|
|
||||||
let env = ConcreteEnv::open(config).unwrap();
|
|
||||||
|
|
||||||
(env, tempdir)
|
|
||||||
}
|
|
|
@ -1,83 +1,7 @@
|
||||||
//! TODO
|
#![allow(unused_crate_dependencies, reason = "used in benchmarks")]
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Lints
|
mod constants;
|
||||||
// Forbid lints.
|
mod tmp_env;
|
||||||
// Our code, and code generated (e.g macros) cannot overrule these.
|
|
||||||
#![forbid(
|
|
||||||
// `unsafe` is allowed but it _must_ be
|
|
||||||
// commented with `SAFETY: reason`.
|
|
||||||
clippy::undocumented_unsafe_blocks,
|
|
||||||
|
|
||||||
// Never.
|
pub use constants::{KEY, VALUE};
|
||||||
unused_unsafe,
|
pub use tmp_env::TmpEnv;
|
||||||
redundant_semicolons,
|
|
||||||
unused_allocation,
|
|
||||||
coherence_leak_check,
|
|
||||||
while_true,
|
|
||||||
clippy::missing_docs_in_private_items,
|
|
||||||
|
|
||||||
// Maybe can be put into `#[deny]`.
|
|
||||||
unconditional_recursion,
|
|
||||||
for_loops_over_fallibles,
|
|
||||||
unused_braces,
|
|
||||||
unused_doc_comments,
|
|
||||||
unused_labels,
|
|
||||||
keyword_idents,
|
|
||||||
non_ascii_idents,
|
|
||||||
variant_size_differences,
|
|
||||||
single_use_lifetimes,
|
|
||||||
|
|
||||||
// Probably can be put into `#[deny]`.
|
|
||||||
future_incompatible,
|
|
||||||
let_underscore,
|
|
||||||
break_with_label_and_loop,
|
|
||||||
duplicate_macro_attributes,
|
|
||||||
exported_private_dependencies,
|
|
||||||
large_assignments,
|
|
||||||
overlapping_range_endpoints,
|
|
||||||
semicolon_in_expressions_from_macros,
|
|
||||||
noop_method_call,
|
|
||||||
unreachable_pub,
|
|
||||||
)]
|
|
||||||
// Deny lints.
|
|
||||||
// Some of these are `#[allow]`'ed on a per-case basis.
|
|
||||||
#![deny(
|
|
||||||
clippy::all,
|
|
||||||
clippy::correctness,
|
|
||||||
clippy::suspicious,
|
|
||||||
clippy::style,
|
|
||||||
clippy::complexity,
|
|
||||||
clippy::perf,
|
|
||||||
clippy::pedantic,
|
|
||||||
clippy::nursery,
|
|
||||||
clippy::cargo,
|
|
||||||
unused_mut,
|
|
||||||
missing_docs,
|
|
||||||
deprecated,
|
|
||||||
unused_comparisons,
|
|
||||||
nonstandard_style
|
|
||||||
)]
|
|
||||||
#![allow(unreachable_code, unused_variables, dead_code, unused_imports)] // TODO: remove
|
|
||||||
#![allow(
|
|
||||||
// FIXME: this lint affects crates outside of
|
|
||||||
// `database/` for some reason, allow for now.
|
|
||||||
clippy::cargo_common_metadata,
|
|
||||||
|
|
||||||
// FIXME: adding `#[must_use]` onto everything
|
|
||||||
// might just be more annoying than useful...
|
|
||||||
// although it is sometimes nice.
|
|
||||||
clippy::must_use_candidate,
|
|
||||||
|
|
||||||
// TODO: should be removed after all `todo!()`'s are gone.
|
|
||||||
clippy::diverging_sub_expression,
|
|
||||||
|
|
||||||
clippy::module_name_repetitions,
|
|
||||||
clippy::module_inception,
|
|
||||||
clippy::redundant_pub_crate,
|
|
||||||
clippy::option_if_let_else,
|
|
||||||
)]
|
|
||||||
// Allow some lints when running in debug mode.
|
|
||||||
#![cfg_attr(debug_assertions, allow(clippy::todo, clippy::multiple_crate_versions))]
|
|
||||||
|
|
||||||
mod helper;
|
|
||||||
pub use helper::{tmp_env, tmp_env_all_threads};
|
|
||||||
|
|
88
benches/criterion/cuprate-database/src/tmp_env.rs
Normal file
88
benches/criterion/cuprate-database/src/tmp_env.rs
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
//! An [`Env`] inside a [`TempDir`].
|
||||||
|
|
||||||
|
use tempfile::TempDir;
|
||||||
|
|
||||||
|
use cuprate_blockchain::tables::Outputs;
|
||||||
|
use cuprate_database::{
|
||||||
|
config::ConfigBuilder, resize::PAGE_SIZE, ConcreteEnv, DatabaseRw, Env, EnvInner, TxRw,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::constants::{KEY, VALUE};
|
||||||
|
|
||||||
|
/// A temporary in-memory [`Env`].
|
||||||
|
///
|
||||||
|
/// This is a [`ConcreteEnv`] that uses [`TempDir`] as the
|
||||||
|
/// backing file location - this is an in-memory file on Linux.
|
||||||
|
pub struct TmpEnv {
|
||||||
|
pub env: ConcreteEnv,
|
||||||
|
pub tempdir: TempDir,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TmpEnv {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TmpEnv {
|
||||||
|
/// Create an `Env` in a temporary directory.
|
||||||
|
///
|
||||||
|
/// The directory is automatically removed after the [`TempDir`] is dropped.
|
||||||
|
#[expect(clippy::missing_panics_doc)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let tempdir = tempfile::tempdir().unwrap();
|
||||||
|
let path = tempdir.path().to_path_buf().into();
|
||||||
|
let config = ConfigBuilder::new(path).low_power().build();
|
||||||
|
let env = ConcreteEnv::open(config).unwrap();
|
||||||
|
|
||||||
|
// Resize to a very large map to prevent resize errors.
|
||||||
|
if ConcreteEnv::MANUAL_RESIZE {
|
||||||
|
// SAFETY: no write transactions exist yet.
|
||||||
|
unsafe {
|
||||||
|
env.env_inner()
|
||||||
|
.resize(PAGE_SIZE.get() * 1024 * 1024 * 1024)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Self { env, tempdir }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inserts [`KEY`] and [`VALUE`] inside the [`Outputs`] table.
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_key_value(self) -> Self {
|
||||||
|
let env_inner = self.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();
|
||||||
|
|
||||||
|
drop(env_inner);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inserts [`VALUE`] inside the [`Outputs`] table 100 times.
|
||||||
|
///
|
||||||
|
/// The key is an incrementing [`KEY`], i.e. the keys are
|
||||||
|
/// `KEY + {0..99}`, each one has [`VALUE`] as the value.
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_key_value_100(self) -> Self {
|
||||||
|
let env_inner = self.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);
|
||||||
|
tx_rw.commit().unwrap();
|
||||||
|
|
||||||
|
drop(env_inner);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue