Skip to content

Commit 7d17d15

Browse files
committed
fix: update benches to use tx per batch
1 parent c992550 commit 7d17d15

File tree

3 files changed

+181
-73
lines changed

3 files changed

+181
-73
lines changed

benches/cursor.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use utils::*;
1010
fn bench_get_seq_iter(c: &mut Criterion) {
1111
let n = 100;
1212
let (_dir, env) = setup_bench_db(n);
13-
let txn = env.begin_ro_txn().unwrap();
13+
let txn = create_ro_sync(&env);
1414
let db = txn.open_db(None).unwrap();
1515
// Note: setup_bench_db creates a named database which adds metadata to the
1616
// main database, so actual item count is n + 1
@@ -57,7 +57,7 @@ fn bench_get_seq_iter(c: &mut Criterion) {
5757
fn bench_get_seq_cursor(c: &mut Criterion) {
5858
let n = 100;
5959
let (_dir, env) = setup_bench_db(n);
60-
let txn = env.begin_ro_txn().unwrap();
60+
let txn = create_ro_sync(&env);
6161
let db = txn.open_db(None).unwrap();
6262
// Note: setup_bench_db creates a named database which adds metadata to the
6363
// main database, so actual item count is n + 1
@@ -80,7 +80,7 @@ fn bench_get_seq_cursor(c: &mut Criterion) {
8080
fn bench_get_seq_for_loop(c: &mut Criterion) {
8181
let n = 100;
8282
let (_dir, env) = setup_bench_db(n);
83-
let txn = env.begin_ro_txn().unwrap();
83+
let txn = create_ro_sync(&env);
8484
let db = txn.open_db(None).unwrap();
8585
// Note: setup_bench_db creates a named database which adds metadata to the
8686
// main database, so actual item count is n + 1
@@ -107,7 +107,7 @@ fn bench_get_seq_for_loop(c: &mut Criterion) {
107107
fn bench_get_seq_iter_single_thread(c: &mut Criterion) {
108108
let n = 100;
109109
let (_dir, env) = setup_bench_db(n);
110-
let mut txn = env.begin_ro_unsync().unwrap();
110+
let mut txn = create_ro_unsync(&env);
111111
let db = txn.open_db(None).unwrap();
112112
// Note: setup_bench_db creates a named database which adds metadata to the
113113
// main database, so actual item count is n + 1
@@ -154,7 +154,7 @@ fn bench_get_seq_iter_single_thread(c: &mut Criterion) {
154154
fn bench_get_seq_cursor_single_thread(c: &mut Criterion) {
155155
let n = 100;
156156
let (_dir, env) = setup_bench_db(n);
157-
let mut txn = env.begin_ro_unsync().unwrap();
157+
let mut txn = create_ro_unsync(&env);
158158
let db = txn.open_db(None).unwrap();
159159
// Note: setup_bench_db creates a named database which adds metadata to the
160160
// main database, so actual item count is n + 1
@@ -177,7 +177,7 @@ fn bench_get_seq_cursor_single_thread(c: &mut Criterion) {
177177
fn bench_get_seq_for_loop_single_thread(c: &mut Criterion) {
178178
let n = 100;
179179
let (_dir, env) = setup_bench_db(n);
180-
let mut txn = env.begin_ro_unsync().unwrap();
180+
let mut txn = create_ro_unsync(&env);
181181
let db = txn.open_db(None).unwrap();
182182
// Note: setup_bench_db creates a named database which adds metadata to the
183183
// main database, so actual item count is n + 1
@@ -205,8 +205,8 @@ fn bench_get_seq_raw(c: &mut Criterion) {
205205
let n = 100;
206206
let (_dir, env) = setup_bench_db(n);
207207

208-
let dbi = env.begin_ro_txn().unwrap().open_db(None).unwrap().dbi();
209-
let txn = env.begin_ro_txn().unwrap();
208+
let dbi = create_ro_sync(&env).open_db(None).unwrap().dbi();
209+
let txn = create_ro_sync(&env);
210210

211211
let mut key = MDBX_val { iov_len: 0, iov_base: ptr::null_mut() };
212212
let mut data = MDBX_val { iov_len: 0, iov_base: ptr::null_mut() };

benches/transaction.rs

Lines changed: 114 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,12 @@ use signet_libmdbx::{ObjectLength, WriteFlags, ffi::*};
77
use std::{hint::black_box, ptr};
88
use utils::*;
99

10-
fn bench_get_rand(c: &mut Criterion) {
11-
let n = 100u32;
12-
let (_dir, env) = setup_bench_db(n);
13-
let txn = env.begin_ro_txn().unwrap();
14-
let db = txn.open_db(None).unwrap();
15-
16-
let mut keys: Vec<String> = (0..n).map(get_key).collect();
17-
keys.shuffle(&mut StdRng::from_seed(Default::default()));
18-
19-
c.bench_function("transaction::get::rand", |b| {
20-
b.iter(|| {
21-
let mut i = 0usize;
22-
for key in &keys {
23-
i += *txn.get::<ObjectLength>(db.dbi(), key.as_bytes()).unwrap().unwrap();
24-
}
25-
black_box(i);
26-
})
27-
});
28-
}
10+
// GET
2911

3012
fn bench_get_rand_raw(c: &mut Criterion) {
3113
let n = 100u32;
3214
let (_dir, env) = setup_bench_db(n);
33-
let txn = env.begin_ro_txn().unwrap();
15+
let txn = create_ro_sync(&env);
3416
let db = txn.open_db(None).unwrap();
3517

3618
let mut keys: Vec<String> = (0..n).map(get_key).collect();
@@ -60,21 +42,69 @@ fn bench_get_rand_raw(c: &mut Criterion) {
6042
});
6143
}
6244

63-
fn bench_put_rand(c: &mut Criterion) {
45+
fn bench_get_rand_sync(c: &mut Criterion) {
46+
let n = 100u32;
47+
let (_dir, env) = setup_bench_db(n);
48+
let txn = create_ro_sync(&env);
49+
let db = txn.open_db(None).unwrap();
50+
51+
let mut keys: Vec<String> = (0..n).map(get_key).collect();
52+
keys.shuffle(&mut StdRng::from_seed(Default::default()));
53+
54+
c.bench_function("transaction::get::rand", |b| {
55+
b.iter(|| {
56+
let mut i = 0usize;
57+
for key in &keys {
58+
i += *txn.get::<ObjectLength>(db.dbi(), key.as_bytes()).unwrap().unwrap();
59+
}
60+
black_box(i);
61+
})
62+
});
63+
}
64+
65+
fn bench_get_rand_unsync(c: &mut Criterion) {
66+
let n = 100u32;
67+
let (_dir, env) = setup_bench_db(n);
68+
let mut txn = create_ro_unsync(&env);
69+
let db = txn.open_db(None).unwrap();
70+
71+
let mut keys: Vec<String> = (0..n).map(get_key).collect();
72+
keys.shuffle(&mut StdRng::from_seed(Default::default()));
73+
74+
c.bench_function("transaction::get::rand::single_thread", |b| {
75+
b.iter(|| {
76+
let mut i = 0usize;
77+
for key in &keys {
78+
i += *txn.get::<ObjectLength>(db.dbi(), key.as_bytes()).unwrap().unwrap();
79+
}
80+
black_box(i);
81+
})
82+
});
83+
}
84+
85+
// PUT
86+
87+
fn bench_put_rand_sync(c: &mut Criterion) {
6488
let n = 100u32;
6589
let (_dir, env) = setup_bench_db(0);
6690

6791
let mut items: Vec<(String, String)> = (0..n).map(|n| (get_key(n), get_data(n))).collect();
6892
items.shuffle(&mut StdRng::from_seed(Default::default()));
6993

7094
c.bench_function("transaction::put::rand", |b| {
71-
b.iter(|| {
72-
let txn = env.begin_rw_txn().unwrap();
73-
let db = txn.open_db(None).unwrap();
74-
for (key, data) in &items {
75-
txn.put(db, key, data, WriteFlags::empty()).unwrap();
76-
}
77-
})
95+
b.iter_batched(
96+
|| {
97+
let txn = create_rw_sync(&env);
98+
let db = txn.open_db(None).unwrap();
99+
(txn, db)
100+
},
101+
|(txn, db)| {
102+
for (key, data) in &items {
103+
txn.put(db, key, data, WriteFlags::empty()).unwrap();
104+
}
105+
},
106+
criterion::BatchSize::PerIteration,
107+
)
78108
});
79109
}
80110

@@ -85,17 +115,21 @@ fn bench_put_rand_raw(c: &mut Criterion) {
85115
let mut items: Vec<(String, String)> = (0..n).map(|n| (get_key(n), get_data(n))).collect();
86116
items.shuffle(&mut StdRng::from_seed(Default::default()));
87117

88-
let dbi = env.begin_ro_txn().unwrap().open_db(None).unwrap().dbi();
118+
let dbi = create_ro_sync(&env).open_db(None).unwrap().dbi();
89119

90120
let mut key_val: MDBX_val = MDBX_val { iov_len: 0, iov_base: ptr::null_mut() };
91121
let mut data_val: MDBX_val = MDBX_val { iov_len: 0, iov_base: ptr::null_mut() };
92122

93123
c.bench_function("transaction::put::rand::raw", |b| {
94-
b.iter(|| unsafe {
95-
let mut txn: *mut MDBX_txn = ptr::null_mut();
96-
env.with_raw_env_ptr(|env| {
97-
mdbx_txn_begin_ex(env, ptr::null_mut(), 0, &raw mut txn, ptr::null_mut());
98-
124+
b.iter_batched(
125+
|| unsafe {
126+
let mut txn: *mut MDBX_txn = ptr::null_mut();
127+
env.with_raw_env_ptr(|env_ptr| {
128+
txn = create_rw_raw(env_ptr);
129+
});
130+
txn
131+
},
132+
|txn| unsafe {
99133
let mut i = 0;
100134
for (key, data) in &items {
101135
key_val.iov_len = key.len();
@@ -107,53 +141,70 @@ fn bench_put_rand_raw(c: &mut Criterion) {
107141
}
108142
assert_eq!(0, i);
109143
mdbx_txn_abort(txn);
110-
});
111-
})
144+
},
145+
criterion::BatchSize::PerIteration,
146+
)
112147
});
113148
}
114149

115-
fn bench_get_rand_unsync(c: &mut Criterion) {
150+
fn bench_put_rand_unsync(c: &mut Criterion) {
116151
let n = 100u32;
117-
let (_dir, env) = setup_bench_db(n);
118-
let mut txn = env.begin_ro_unsync().unwrap();
119-
let db = txn.open_db(None).unwrap();
152+
let (_dir, env) = setup_bench_db(0);
120153

121-
let mut keys: Vec<String> = (0..n).map(get_key).collect();
122-
keys.shuffle(&mut StdRng::from_seed(Default::default()));
154+
let mut items: Vec<(String, String)> = (0..n).map(|n| (get_key(n), get_data(n))).collect();
155+
items.shuffle(&mut StdRng::from_seed(Default::default()));
123156

124-
c.bench_function("transaction::get::rand::single_thread", |b| {
125-
b.iter(|| {
126-
let mut i = 0usize;
127-
for key in &keys {
128-
i += *txn.get::<ObjectLength>(db.dbi(), key.as_bytes()).unwrap().unwrap();
129-
}
130-
black_box(i);
157+
c.bench_function("transaction::put::rand::single_thread", |b| {
158+
b.iter_batched(
159+
|| {
160+
let mut txn = create_rw_unsync(&env);
161+
let db = txn.open_db(None).unwrap();
162+
(txn, db)
163+
},
164+
|(mut txn, db)| {
165+
for (key, data) in &items {
166+
txn.put(db, key, data, WriteFlags::empty()).unwrap();
167+
}
168+
},
169+
criterion::BatchSize::PerIteration,
170+
)
171+
});
172+
}
173+
174+
// CREATE
175+
176+
fn bench_tx_create_raw(c: &mut Criterion) {
177+
let (_dir, env) = setup_bench_db(0);
178+
179+
c.bench_function("transaction::create::raw", |b| {
180+
b.iter(|| unsafe {
181+
env.with_raw_env_ptr(|env_ptr| {
182+
let txn = create_ro_raw(env_ptr);
183+
mdbx_txn_abort(txn);
184+
})
131185
})
132186
});
133187
}
134188

135-
fn bench_put_rand_unsync(c: &mut Criterion) {
136-
let n = 100u32;
189+
fn bench_tx_create_sync(c: &mut Criterion) {
137190
let (_dir, env) = setup_bench_db(0);
138191

139-
let mut items: Vec<(String, String)> = (0..n).map(|n| (get_key(n), get_data(n))).collect();
140-
items.shuffle(&mut StdRng::from_seed(Default::default()));
192+
c.bench_function("transaction::create::sync", |b| b.iter(|| black_box(create_ro_sync(&env))));
193+
}
141194

142-
c.bench_function("transaction::put::rand::single_thread", |b| {
143-
b.iter(|| {
144-
let mut txn = env.begin_rw_unsync().unwrap();
145-
let db = txn.open_db(None).unwrap();
146-
for (key, data) in &items {
147-
txn.put(db, key, data, WriteFlags::empty()).unwrap();
148-
}
149-
})
195+
fn bench_tx_create_unsync(c: &mut Criterion) {
196+
let (_dir, env) = setup_bench_db(0);
197+
198+
c.bench_function("transaction::create::unsync", |b| {
199+
b.iter(|| black_box(create_ro_unsync(&env)))
150200
});
151201
}
152202

153203
criterion_group! {
154204
name = benches;
155205
config = Criterion::default();
156-
targets = bench_get_rand, bench_get_rand_raw, bench_put_rand, bench_put_rand_raw,
157-
bench_get_rand_unsync, bench_put_rand_unsync
206+
targets = bench_get_rand_sync, bench_get_rand_raw, bench_get_rand_unsync,
207+
bench_put_rand_sync, bench_put_rand_raw, bench_put_rand_unsync,
208+
bench_tx_create_raw, bench_tx_create_sync, bench_tx_create_unsync
158209
}
159210
criterion_main!(benches);

benches/utils.rs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
//! Utility functions for benchmarks.
2-
#![allow(unreachable_pub)]
2+
#![allow(dead_code, unreachable_pub)]
33

4-
use signet_libmdbx::{Environment, WriteFlags};
4+
use signet_libmdbx::{
5+
Environment, WriteFlags,
6+
ffi::{MDBX_TXN_RDONLY, MDBX_env, MDBX_txn, mdbx_txn_begin_ex},
7+
tx::{RoTxSync, RoTxUnsync, RwTxSync, RwTxUnsync},
8+
};
9+
use std::ptr;
510
use tempfile::{TempDir, tempdir};
611

712
/// Name of the named benchmark database.
@@ -17,6 +22,58 @@ pub fn get_data(n: u32) -> String {
1722
format!("data{n}")
1823
}
1924

25+
// Raw transaction utilities
26+
27+
/// Create a raw read-only transaction from an environment pointer.
28+
///
29+
/// # Safety
30+
///
31+
/// The caller must ensure `env` is a valid environment pointer.
32+
#[inline(always)]
33+
pub unsafe fn create_ro_raw(env: *mut MDBX_env) -> *mut MDBX_txn {
34+
let mut txn: *mut MDBX_txn = ptr::null_mut();
35+
// SAFETY: Caller guarantees env is valid.
36+
unsafe { mdbx_txn_begin_ex(env, ptr::null_mut(), MDBX_TXN_RDONLY, &mut txn, ptr::null_mut()) };
37+
txn
38+
}
39+
40+
/// Create a raw read-write transaction from an environment pointer.
41+
///
42+
/// # Safety
43+
///
44+
/// The caller must ensure `env` is a valid environment pointer.
45+
#[inline(always)]
46+
pub unsafe fn create_rw_raw(env: *mut MDBX_env) -> *mut MDBX_txn {
47+
let mut txn: *mut MDBX_txn = ptr::null_mut();
48+
// SAFETY: Caller guarantees env is valid.
49+
unsafe { mdbx_txn_begin_ex(env, ptr::null_mut(), 0, &mut txn, ptr::null_mut()) };
50+
txn
51+
}
52+
53+
// Sync transaction utilities
54+
55+
/// Create a read-only synchronized transaction.
56+
pub fn create_ro_sync(env: &Environment) -> RoTxSync {
57+
env.begin_ro_txn().unwrap()
58+
}
59+
60+
/// Create a read-write synchronized transaction.
61+
pub fn create_rw_sync(env: &Environment) -> RwTxSync {
62+
env.begin_rw_txn().unwrap()
63+
}
64+
65+
// Unsync transaction utilities
66+
67+
/// Create a read-only unsynchronized transaction.
68+
pub fn create_ro_unsync(env: &Environment) -> RoTxUnsync {
69+
env.begin_ro_unsync().unwrap()
70+
}
71+
72+
/// Create a read-write unsynchronized transaction.
73+
pub fn create_rw_unsync(env: &Environment) -> RwTxUnsync {
74+
env.begin_rw_unsync().unwrap()
75+
}
76+
2077
/// Create a temporary benchmark database with the specified number of rows.
2178
pub fn setup_bench_db(num_rows: u32) -> (TempDir, Environment) {
2279
let dir = tempdir().unwrap();

0 commit comments

Comments
 (0)