mirror of
https://github.com/hinto-janai/cuprate.git
synced 2025-01-24 11:26:03 +00:00
copy #98
This commit is contained in:
parent
1c462e3c95
commit
7a94952e14
11 changed files with 1872 additions and 0 deletions
24
benches/criterion/cuprate-database/Cargo.toml
Normal file
24
benches/criterion/cuprate-database/Cargo.toml
Normal file
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "cuprate-database-benchmark"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
description = "Benchmarking for Cuprate's database abstraction"
|
||||
license = "MIT"
|
||||
authors = ["hinto-janai"]
|
||||
repository = "https://github.com/Cuprate/cuprate/tree/main/database/benchmark"
|
||||
keywords = ["cuprate", "database", "benchmark"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
criterion = { workspace = true }
|
||||
cuprate-database = { path = "../", features = ["default"] }
|
||||
cuprate-helper = { path = "../../helper", features = ["fs", "thread"] }
|
||||
# cuprate-types = { path = "../../types", features = ["service"] }
|
||||
function_name = { version = "0.3.0" }
|
||||
tempfile = { version = "3.10.0" }
|
||||
|
||||
[[bench]]
|
||||
name = "main"
|
||||
harness = false
|
48
benches/criterion/cuprate-database/README.md
Normal file
48
benches/criterion/cuprate-database/README.md
Normal file
|
@ -0,0 +1,48 @@
|
|||
# `cuprate-database-benchmark`
|
||||
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
|
||||
|
||||
<!-- Did you know markdown automatically increments number lists, even if they are all 1...? -->
|
||||
1. [Usage](#Usage)
|
||||
1. [File Structure](#file-structure)
|
||||
- [`src/`](#src)
|
||||
- [`benches/`](#benches)
|
||||
|
||||
# Usage
|
||||
Ensure the system is as quiet as possible (no background tasks) before starting and during the benchmarks.
|
||||
|
||||
To start all benchmarks, run:
|
||||
```bash
|
||||
cargo bench --package cuprate-database-benchmarks
|
||||
```
|
||||
|
||||
# File Structure
|
||||
A quick reference of the structure of the folders & files in `cuprate-database`.
|
||||
|
||||
Note that `lib.rs/mod.rs` files are purely for re-exporting/visibility/lints, and contain no code. Each sub-directory has a corresponding `mod.rs`.
|
||||
|
||||
## `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
|
||||
| `service.rs` | `cuprate_database::service` benchmarks
|
||||
| `storable.rs` | `trait Storable` benchmarks
|
583
benches/criterion/cuprate-database/benches/db.rs
Normal file
583
benches/criterion/cuprate-database/benches/db.rs
Normal file
|
@ -0,0 +1,583 @@
|
|||
//! `trait Database{Ro,Rw,Iter}` 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;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- 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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
// 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();
|
||||
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();
|
||||
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());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
584
benches/criterion/cuprate-database/benches/db_multi_thread.rs
Normal file
584
benches/criterion/cuprate-database/benches/db_multi_thread.rs
Normal file
|
@ -0,0 +1,584 @@
|
|||
//! 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());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
161
benches/criterion/cuprate-database/benches/env.rs
Normal file
161
benches/criterion/cuprate-database/benches/env.rs
Normal file
|
@ -0,0 +1,161 @@
|
|||
//! `trait {Env, EnvInner, TxR{o,w}, Tables[Mut]}` 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;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- 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();
|
||||
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
|
||||
// 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();
|
||||
|
||||
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();
|
||||
|
||||
c.bench_function(function_name!(), |b| {
|
||||
b.iter(|| {
|
||||
black_box(env.disk_size_bytes()).unwrap();
|
||||
});
|
||||
});
|
||||
}
|
162
benches/criterion/cuprate-database/benches/env_multi_thread.rs
Normal file
162
benches/criterion/cuprate-database/benches/env_multi_thread.rs
Normal file
|
@ -0,0 +1,162 @@
|
|||
//! 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();
|
||||
});
|
||||
});
|
||||
}
|
91
benches/criterion/cuprate-database/benches/main.rs
Normal file
91
benches/criterion/cuprate-database/benches/main.rs
Normal file
|
@ -0,0 +1,91 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- 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 env;
|
||||
mod storable;
|
||||
|
||||
criterion::criterion_main! {
|
||||
db::benches,
|
||||
env::benches,
|
||||
storable::benches,
|
||||
}
|
25
benches/criterion/cuprate-database/benches/service.rs
Normal file
25
benches/criterion/cuprate-database/benches/service.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
//! `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
|
81
benches/criterion/cuprate-database/benches/storable.rs
Normal file
81
benches/criterion/cuprate-database/benches/storable.rs
Normal file
|
@ -0,0 +1,81 @@
|
|||
//! `trait Storable` benchmarks.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
|
||||
use function_name::named;
|
||||
|
||||
use cuprate_database::{
|
||||
types::{Output, PreRctOutputId},
|
||||
Storable,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Criterion
|
||||
criterion_group! {
|
||||
benches,
|
||||
pre_rct_output_id_as_bytes,
|
||||
pre_rct_output_id_from_bytes,
|
||||
output_as_bytes,
|
||||
output_from_bytes
|
||||
}
|
||||
criterion_main!(benches);
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Constants
|
||||
/// 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.
|
||||
#[named]
|
||||
fn pre_rct_output_id_as_bytes(c: &mut Criterion) {
|
||||
c.bench_function(function_name!(), |b| {
|
||||
b.iter(|| {
|
||||
black_box(Storable::as_bytes(black_box(&PRE_RCT_OUTPUT_ID)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// [`PreRctOutputId`] cast from bytes.
|
||||
#[named]
|
||||
fn pre_rct_output_id_from_bytes(c: &mut Criterion) {
|
||||
let bytes = Storable::as_bytes(&PRE_RCT_OUTPUT_ID);
|
||||
|
||||
c.bench_function(function_name!(), |b| {
|
||||
b.iter(|| {
|
||||
let _: PreRctOutputId = black_box(Storable::from_bytes(black_box(bytes)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// [`Output`] cast as bytes.
|
||||
#[named]
|
||||
fn output_as_bytes(c: &mut Criterion) {
|
||||
c.bench_function(function_name!(), |b| {
|
||||
b.iter(|| {
|
||||
black_box(Storable::as_bytes(black_box(&OUTPUT)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// [`Output`] cast from bytes.
|
||||
#[named]
|
||||
fn output_from_bytes(c: &mut Criterion) {
|
||||
let bytes = Storable::as_bytes(&OUTPUT);
|
||||
|
||||
c.bench_function(function_name!(), |b| {
|
||||
b.iter(|| {
|
||||
let _: Output = black_box(Storable::from_bytes(black_box(bytes)));
|
||||
});
|
||||
});
|
||||
}
|
30
benches/criterion/cuprate-database/src/helper.rs
Normal file
30
benches/criterion/cuprate-database/src/helper.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
//! 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)
|
||||
}
|
83
benches/criterion/cuprate-database/src/lib.rs
Normal file
83
benches/criterion/cuprate-database/src/lib.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- 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,
|
||||
)]
|
||||
// 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};
|
Loading…
Reference in a new issue