#![allow(missing_docs)] use criterion::{ black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, }; use pprof::criterion::{Output, PProfProfiler}; use reth_db::tables::*; use reth_db_api::{ cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW}, table::{Decode, Decompress, DupSort}, transaction::DbTx, }; criterion_group! { name = benches; config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); targets = db, serialization } criterion_main!(benches); pub fn db(c: &mut Criterion) { let mut group = c.benchmark_group("tables_db"); group.measurement_time(std::time::Duration::from_millis(200)); group.warm_up_time(std::time::Duration::from_millis(200)); measure_table_db::(&mut group); measure_table_db::(&mut group); measure_table_db::(&mut group); measure_table_db::(&mut group); measure_table_db::(&mut group); measure_table_db::(&mut group); measure_table_db::(&mut group); measure_table_db::(&mut group); measure_dupsort_db::(&mut group); measure_table_db::(&mut group); } pub fn serialization(c: &mut Criterion) { let mut group = c.benchmark_group("tables_serialization"); group.measurement_time(std::time::Duration::from_millis(200)); group.warm_up_time(std::time::Duration::from_millis(200)); measure_table_serialization::(&mut group); measure_table_serialization::(&mut group); measure_table_serialization::(&mut group); measure_table_serialization::(&mut group); measure_table_serialization::(&mut group); measure_table_serialization::(&mut group); measure_table_serialization::(&mut group); measure_table_serialization::(&mut group); measure_table_serialization::(&mut group); measure_table_serialization::(&mut group); } /// Measures `Encode`, `Decode`, `Compress` and `Decompress`. fn measure_table_serialization(group: &mut BenchmarkGroup<'_, WallTime>) where T: Table, T::Key: Default + Clone + for<'de> serde::Deserialize<'de>, T::Value: Default + Clone + for<'de> serde::Deserialize<'de>, { let input = &load_vectors::(); group.bench_function(format!("{}.KeyEncode", T::NAME), move |b| { b.iter_with_setup( || input.clone(), |input| { { for (k, _, _, _) in input { k.encode(); } }; black_box(()); }, ) }); group.bench_function(format!("{}.KeyDecode", T::NAME), |b| { b.iter_with_setup( || input.clone(), |input| { { for (_, k, _, _) in input { let _ = ::Key::decode(k); } }; black_box(()); }, ) }); group.bench_function(format!("{}.ValueCompress", T::NAME), move |b| { b.iter_with_setup( || input.clone(), |input| { { for (_, _, v, _) in input { v.compress(); } }; black_box(()); }, ) }); group.bench_function(format!("{}.ValueDecompress", T::NAME), |b| { b.iter_with_setup( || input.clone(), |input| { { for (_, _, _, v) in input { let _ = ::Value::decompress(v); } }; black_box(()); }, ) }); } /// Measures `SeqWrite`, `RandomWrite`, `SeqRead` and `RandomRead` using `cursor` and `tx.put`. fn measure_table_db(group: &mut BenchmarkGroup<'_, WallTime>) where T: Table, T::Key: Default + Clone + for<'de> serde::Deserialize<'de>, T::Value: Default + Clone + for<'de> serde::Deserialize<'de>, { let input = &load_vectors::(); let bench_db_path = Path::new(BENCH_DB_PATH); group.bench_function(format!("{}.SeqWrite", T::NAME), |b| { b.iter_with_setup( || { // Reset DB let _ = fs::remove_dir_all(bench_db_path); ( input.clone(), Arc::try_unwrap(create_test_rw_db_with_path(bench_db_path)).unwrap(), ) }, |(input, db)| { // Create TX let tx = db.tx_mut().expect("tx"); let mut crsr = tx.cursor_write::().expect("cursor"); black_box({ for (k, _, v, _) in input { crsr.append(k, v).expect("submit"); } tx.inner.commit().unwrap() }); }, ) }); group.bench_function(format!("{}.RandomWrite", T::NAME), |b| { b.iter_with_setup( || { // Reset DB let _ = fs::remove_dir_all(bench_db_path); (input, Arc::try_unwrap(create_test_rw_db_with_path(bench_db_path)).unwrap()) }, |(input, db)| { // Create TX let tx = db.tx_mut().expect("tx"); let mut crsr = tx.cursor_write::().expect("cursor"); black_box({ for index in RANDOM_INDEXES { let (k, _, v, _) = input.get(index).unwrap().clone(); crsr.insert(k, v).expect("submit"); } tx.inner.commit().unwrap() }); }, ) }); group.bench_function(format!("{}.SeqRead", T::NAME), |b| { let db = set_up_db::(bench_db_path, input); b.iter(|| { // Create TX let tx = db.tx().expect("tx"); { let mut cursor = tx.cursor_read::().expect("cursor"); let walker = cursor.walk(Some(input.first().unwrap().0.clone())).unwrap(); for element in walker { element.unwrap(); } }; black_box(()); }) }); group.bench_function(format!("{}.RandomRead", T::NAME), |b| { let db = set_up_db::(bench_db_path, input); b.iter(|| { // Create TX let tx = db.tx().expect("tx"); { for index in RANDOM_INDEXES { let mut cursor = tx.cursor_read::().expect("cursor"); cursor.seek_exact(input.get(index).unwrap().0.clone()).unwrap(); } }; black_box(()); }) }); } /// Measures `SeqWrite`, `RandomWrite` and `SeqRead` using `cursor_dup` and `tx.put`. fn measure_dupsort_db(group: &mut BenchmarkGroup<'_, WallTime>) where T: Table + DupSort, T::Key: Default + Clone + for<'de> serde::Deserialize<'de>, T::Value: Default + Clone + for<'de> serde::Deserialize<'de>, T::SubKey: Default + Clone + for<'de> serde::Deserialize<'de>, { let input = &load_vectors::(); let bench_db_path = Path::new(BENCH_DB_PATH); group.bench_function(format!("{}.SeqWrite", T::NAME), |b| { b.iter_with_setup( || { // Reset DB let _ = fs::remove_dir_all(bench_db_path); ( input.clone(), Arc::try_unwrap(create_test_rw_db_with_path(bench_db_path)).unwrap(), ) }, |(input, db)| { // Create TX let tx = db.tx_mut().expect("tx"); let mut crsr = tx.cursor_dup_write::().expect("cursor"); black_box({ for (k, _, v, _) in input { crsr.append_dup(k, v).expect("submit"); } tx.inner.commit().unwrap() }); }, ) }); group.bench_function(format!("{}.RandomWrite", T::NAME), |b| { b.iter_with_setup( || { // Reset DB let _ = fs::remove_dir_all(bench_db_path); (input, Arc::try_unwrap(create_test_rw_db_with_path(bench_db_path)).unwrap()) }, |(input, db)| { // Create TX let tx = db.tx_mut().expect("tx"); for index in RANDOM_INDEXES { let (k, _, v, _) = input.get(index).unwrap().clone(); tx.put::(k, v).unwrap(); } tx.inner.commit().unwrap(); }, ) }); group.bench_function(format!("{}.SeqRead", T::NAME), |b| { let db = set_up_db::(bench_db_path, input); b.iter(|| { // Create TX let tx = db.tx().expect("tx"); { let mut cursor = tx.cursor_dup_read::().expect("cursor"); let walker = cursor.walk_dup(None, Some(T::SubKey::default())).unwrap(); for element in walker { element.unwrap(); } }; black_box(()); }) }); // group.bench_function(format!("{}.RandomRead", T::NAME), |b| {}); } include!("./utils.rs");