Skip to main content

oracle_performance/
oracle_performance.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use std::{sync::Arc, thread::spawn, time::Instant};
5
6use reifydb_codec::{key::serializer::KeySerializer, row::bytes::EncodedBytes};
7use reifydb_core::{interface::catalog::id::QueueId, key::queue::QueueDeduplicationKey};
8use reifydb_transaction::multi::transaction::MultiTransaction;
9use reifydb_value::util::cowvec::CowVec;
10
11trait KeyBytes {
12	fn key_bytes(&self) -> Vec<u8>;
13}
14
15impl KeyBytes for i32 {
16	fn key_bytes(&self) -> Vec<u8> {
17		let mut ser = KeySerializer::new();
18		ser.extend_i32(*self);
19		ser.finish().as_slice().to_vec()
20	}
21}
22
23impl KeyBytes for String {
24	fn key_bytes(&self) -> Vec<u8> {
25		let mut ser = KeySerializer::new();
26		ser.extend_str(self);
27		ser.finish().as_slice().to_vec()
28	}
29}
30
31macro_rules! as_key {
32	($key:expr) => {{ QueueDeduplicationKey::new(QueueId(1), $key.key_bytes().iter().map(|b| !b).collect::<Vec<u8>>()) }};
33}
34
35macro_rules! as_values {
36	($val:expr) => {{ EncodedBytes(CowVec::new($val.key_bytes())) }};
37}
38
39pub fn oracle_performance_benchmark() {
40	println!("=== Oracle Performance Benchmark ===\n");
41
42	let test_sizes = vec![1000, 5000, 10000, 25000];
43
44	for &num_txns in &test_sizes {
45		println!("Testing with {} transactions...", num_txns);
46
47		let engine = MultiTransaction::testing();
48
49		let start = Instant::now();
50
51		for i in 0..num_txns {
52			let mut tx = engine.begin_command().unwrap();
53
54			let key = as_key!(format!("key_{}", i));
55			let value = as_values!(format!("value_{}", i));
56
57			tx.set(&key, value).unwrap();
58			tx.commit(vec![]).unwrap();
59		}
60
61		let duration = start.elapsed();
62		let tps = num_txns as f64 / duration.as_secs_f64();
63
64		println!("  {} transactions in {:?}", num_txns, duration);
65		println!("  {:.0} TPS (transactions per second)", tps);
66		println!("  {:.2} μs per transaction\n", duration.as_micros() as f64 / num_txns as f64);
67	}
68}
69
70pub fn concurrent_oracle_benchmark() {
71	println!("=== Concurrent Oracle Performance Benchmark ===\n");
72
73	let test_configs = vec![(10, 1000), (50, 500), (100, 250), (1000, 50)];
74
75	for &(num_threads, txns_per_thread) in &test_configs {
76		let total_txns = num_threads * txns_per_thread;
77		println!(
78			"Testing {} threads × {} transactions = {} total...",
79			num_threads, txns_per_thread, total_txns
80		);
81
82		let engine = Arc::new(MultiTransaction::testing());
83		let start = Instant::now();
84
85		let mut handles = vec![];
86
87		for thread_id in 0..num_threads {
88			let engine_clone = engine.clone();
89			let handle = spawn(move || {
90				let base_key = thread_id * txns_per_thread;
91				for i in 0..txns_per_thread {
92					let mut tx = engine_clone.begin_command().unwrap();
93
94					let key = as_key!(base_key + i);
95					let value = as_values!(i);
96
97					tx.set(&key, value).unwrap();
98					tx.commit(vec![]).unwrap();
99				}
100			});
101			handles.push(handle);
102		}
103
104		for handle in handles {
105			handle.join().expect("Task panicked");
106		}
107
108		let duration = start.elapsed();
109		let tps = total_txns as f64 / duration.as_secs_f64();
110
111		println!("  {} total transactions in {:?}", total_txns, duration);
112		println!("  {:.0} TPS (transactions per second)", tps);
113		println!("  {:.2} μs per transaction\n", duration.as_micros() as f64 / total_txns as f64);
114	}
115}
116
117pub fn conflict_detection_benchmark() {
118	println!("=== Conflict Detection Performance Benchmark ===\n");
119
120	let engine = MultiTransaction::testing();
121
122	for i in 0..1000 {
123		let mut tx = engine.begin_command().unwrap();
124		let key = as_key!(format!("shared_key_{}", i % 100));
125		let value = as_values!(i);
126		tx.set(&key, value).unwrap();
127		tx.commit(vec![]).unwrap();
128	}
129
130	println!("Pre-populated with 1000 transactions across 100 keys");
131
132	let num_conflict_txns = 10000;
133	let start = Instant::now();
134	let mut conflicts = 0;
135
136	for i in 0..num_conflict_txns {
137		let mut tx = engine.begin_command().unwrap();
138
139		let key = as_key!(format!("shared_key_{}", i % 100));
140		let value = as_values!(i + 1000);
141
142		tx.set(&key, value).unwrap();
143
144		match tx.commit(vec![]) {
145			Ok(_) => {}
146			Err(e) if e.code == "TXN_001" => {
147				conflicts += 1;
148			}
149			Err(e) => panic!("Unexpected error: {:?}", e),
150		};
151	}
152
153	let duration = start.elapsed();
154	let tps = num_conflict_txns as f64 / duration.as_secs_f64();
155
156	println!("  {} transactions with potential conflicts in {:?}", num_conflict_txns, duration);
157	println!(
158		"  {} actual conflicts detected ({:.1}%)",
159		conflicts,
160		conflicts as f64 / num_conflict_txns as f64 * 100.0
161	);
162	println!("  {:.0} TPS (transactions per second)", tps);
163	println!("  {:.2} μs per transaction", duration.as_micros() as f64 / num_conflict_txns as f64);
164}
165
166fn main() {
167	println!("🚀 ReifyDB Oracle Performance Benchmarks\n");
168
169	oracle_performance_benchmark();
170	println!("\n{}\n", "=".repeat(60));
171
172	concurrent_oracle_benchmark();
173	println!("\n{}\n", "=".repeat(60));
174
175	conflict_detection_benchmark();
176
177	println!("\n✅ All benchmarks completed!");
178}