oracle_performance/
oracle_performance.rs1use 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}