benchmarking
This commit is contained in:
		
							
								
								
									
										317
									
								
								benches/concurrent_ops.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								benches/concurrent_ops.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,317 @@ | ||||
| // benches/concurrent_ops.rs | ||||
| use criterion::{criterion_group, criterion_main, Criterion, BenchmarkId}; | ||||
| use tokio::runtime::Runtime; | ||||
| use std::sync::Arc; | ||||
|  | ||||
| mod common; | ||||
| use common::*; | ||||
|  | ||||
| /// Benchmark concurrent write operations | ||||
| fn bench_concurrent_writes(c: &mut Criterion) { | ||||
|     let mut group = c.benchmark_group("concurrent_ops/writes"); | ||||
|      | ||||
|     for num_clients in [10, 50] { | ||||
|         for backend_type in BackendType::all() { | ||||
|             let backend = BenchmarkBackend::new(backend_type).expect("Failed to create backend"); | ||||
|             let storage = backend.storage.clone(); | ||||
|              | ||||
|             group.bench_with_input( | ||||
|                 BenchmarkId::new(format!("{}/clients", backend.name()), num_clients), | ||||
|                 &(storage, num_clients), | ||||
|                 |b, (storage, num_clients)| { | ||||
|                     let rt = Runtime::new().unwrap(); | ||||
|                     b.to_async(&rt).iter(|| { | ||||
|                         let storage = storage.clone(); | ||||
|                         let num_clients = *num_clients; | ||||
|                         async move { | ||||
|                             let mut tasks = Vec::new(); | ||||
|                              | ||||
|                             for client_id in 0..num_clients { | ||||
|                                 let storage = storage.clone(); | ||||
|                                 let task = tokio::spawn(async move { | ||||
|                                     let mut generator = DataGenerator::new(42 + client_id as u64); | ||||
|                                     for i in 0..100 { | ||||
|                                         let key = format!("client:{}:key:{}", client_id, i); | ||||
|                                         let value = generator.generate_value(100); | ||||
|                                         storage.set(key, value).unwrap(); | ||||
|                                     } | ||||
|                                 }); | ||||
|                                 tasks.push(task); | ||||
|                             } | ||||
|                              | ||||
|                             for task in tasks { | ||||
|                                 task.await.unwrap(); | ||||
|                             } | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     group.finish(); | ||||
| } | ||||
|  | ||||
| /// Benchmark concurrent read operations | ||||
| fn bench_concurrent_reads(c: &mut Criterion) { | ||||
|     let mut group = c.benchmark_group("concurrent_ops/reads"); | ||||
|      | ||||
|     for num_clients in [10, 50] { | ||||
|         for backend_type in BackendType::all() { | ||||
|             // Pre-populate with data | ||||
|             let backend = setup_populated_backend(backend_type, 10_000, 100) | ||||
|                 .expect("Failed to setup backend"); | ||||
|             let storage = backend.storage.clone(); | ||||
|              | ||||
|             group.bench_with_input( | ||||
|                 BenchmarkId::new(format!("{}/clients", backend.name()), num_clients), | ||||
|                 &(storage, num_clients), | ||||
|                 |b, (storage, num_clients)| { | ||||
|                     let rt = Runtime::new().unwrap(); | ||||
|                     b.to_async(&rt).iter(|| { | ||||
|                         let storage = storage.clone(); | ||||
|                         let num_clients = *num_clients; | ||||
|                         async move { | ||||
|                             let mut tasks = Vec::new(); | ||||
|                              | ||||
|                             for client_id in 0..num_clients { | ||||
|                                 let storage = storage.clone(); | ||||
|                                 let task = tokio::spawn(async move { | ||||
|                                     let generator = DataGenerator::new(42); | ||||
|                                     for i in 0..100 { | ||||
|                                         let key_id = (client_id * 100 + i) % 10_000; | ||||
|                                         let key = generator.generate_key("bench:key", key_id); | ||||
|                                         storage.get(&key).unwrap(); | ||||
|                                     } | ||||
|                                 }); | ||||
|                                 tasks.push(task); | ||||
|                             } | ||||
|                              | ||||
|                             for task in tasks { | ||||
|                                 task.await.unwrap(); | ||||
|                             } | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     group.finish(); | ||||
| } | ||||
|  | ||||
| /// Benchmark mixed concurrent workload (70% reads, 30% writes) | ||||
| fn bench_concurrent_mixed(c: &mut Criterion) { | ||||
|     let mut group = c.benchmark_group("concurrent_ops/mixed"); | ||||
|      | ||||
|     for num_clients in [10, 50] { | ||||
|         for backend_type in BackendType::all() { | ||||
|             // Pre-populate with data | ||||
|             let backend = setup_populated_backend(backend_type, 10_000, 100) | ||||
|                 .expect("Failed to setup backend"); | ||||
|             let storage = backend.storage.clone(); | ||||
|              | ||||
|             group.bench_with_input( | ||||
|                 BenchmarkId::new(format!("{}/clients", backend.name()), num_clients), | ||||
|                 &(storage, num_clients), | ||||
|                 |b, (storage, num_clients)| { | ||||
|                     let rt = Runtime::new().unwrap(); | ||||
|                     b.to_async(&rt).iter(|| { | ||||
|                         let storage = storage.clone(); | ||||
|                         let num_clients = *num_clients; | ||||
|                         async move { | ||||
|                             let mut tasks = Vec::new(); | ||||
|                              | ||||
|                             for client_id in 0..num_clients { | ||||
|                                 let storage = storage.clone(); | ||||
|                                 let task = tokio::spawn(async move { | ||||
|                                     let mut generator = DataGenerator::new(42 + client_id as u64); | ||||
|                                     for i in 0..100 { | ||||
|                                         if i % 10 < 7 { | ||||
|                                             // 70% reads | ||||
|                                             let key_id = (client_id * 100 + i) % 10_000; | ||||
|                                             let key = generator.generate_key("bench:key", key_id); | ||||
|                                             storage.get(&key).unwrap(); | ||||
|                                         } else { | ||||
|                                             // 30% writes | ||||
|                                             let key = format!("client:{}:key:{}", client_id, i); | ||||
|                                             let value = generator.generate_value(100); | ||||
|                                             storage.set(key, value).unwrap(); | ||||
|                                         } | ||||
|                                     } | ||||
|                                 }); | ||||
|                                 tasks.push(task); | ||||
|                             } | ||||
|                              | ||||
|                             for task in tasks { | ||||
|                                 task.await.unwrap(); | ||||
|                             } | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     group.finish(); | ||||
| } | ||||
|  | ||||
| /// Benchmark concurrent hash operations | ||||
| fn bench_concurrent_hash_ops(c: &mut Criterion) { | ||||
|     let mut group = c.benchmark_group("concurrent_ops/hash_ops"); | ||||
|      | ||||
|     for num_clients in [10, 50] { | ||||
|         for backend_type in BackendType::all() { | ||||
|             let backend = BenchmarkBackend::new(backend_type).expect("Failed to create backend"); | ||||
|             let storage = backend.storage.clone(); | ||||
|              | ||||
|             group.bench_with_input( | ||||
|                 BenchmarkId::new(format!("{}/clients", backend.name()), num_clients), | ||||
|                 &(storage, num_clients), | ||||
|                 |b, (storage, num_clients)| { | ||||
|                     let rt = Runtime::new().unwrap(); | ||||
|                     b.to_async(&rt).iter(|| { | ||||
|                         let storage = storage.clone(); | ||||
|                         let num_clients = *num_clients; | ||||
|                         async move { | ||||
|                             let mut tasks = Vec::new(); | ||||
|                              | ||||
|                             for client_id in 0..num_clients { | ||||
|                                 let storage = storage.clone(); | ||||
|                                 let task = tokio::spawn(async move { | ||||
|                                     let mut generator = DataGenerator::new(42 + client_id as u64); | ||||
|                                     for i in 0..50 { | ||||
|                                         let key = format!("client:{}:hash:{}", client_id, i); | ||||
|                                         let field = format!("field{}", i % 10); | ||||
|                                         let value = generator.generate_value(100); | ||||
|                                         storage.hset(&key, vec![(field, value)]).unwrap(); | ||||
|                                     } | ||||
|                                 }); | ||||
|                                 tasks.push(task); | ||||
|                             } | ||||
|                              | ||||
|                             for task in tasks { | ||||
|                                 task.await.unwrap(); | ||||
|                             } | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     group.finish(); | ||||
| } | ||||
|  | ||||
| /// Benchmark concurrent list operations | ||||
| fn bench_concurrent_list_ops(c: &mut Criterion) { | ||||
|     let mut group = c.benchmark_group("concurrent_ops/list_ops"); | ||||
|      | ||||
|     for num_clients in [10, 50] { | ||||
|         for backend_type in BackendType::all() { | ||||
|             let backend = BenchmarkBackend::new(backend_type).expect("Failed to create backend"); | ||||
|             let storage = backend.storage.clone(); | ||||
|              | ||||
|             group.bench_with_input( | ||||
|                 BenchmarkId::new(format!("{}/clients", backend.name()), num_clients), | ||||
|                 &(storage, num_clients), | ||||
|                 |b, (storage, num_clients)| { | ||||
|                     let rt = Runtime::new().unwrap(); | ||||
|                     b.to_async(&rt).iter(|| { | ||||
|                         let storage = storage.clone(); | ||||
|                         let num_clients = *num_clients; | ||||
|                         async move { | ||||
|                             let mut tasks = Vec::new(); | ||||
|                              | ||||
|                             for client_id in 0..num_clients { | ||||
|                                 let storage = storage.clone(); | ||||
|                                 let task = tokio::spawn(async move { | ||||
|                                     let mut generator = DataGenerator::new(42 + client_id as u64); | ||||
|                                     for i in 0..50 { | ||||
|                                         let key = format!("client:{}:list:{}", client_id, i); | ||||
|                                         let element = generator.generate_value(100); | ||||
|                                         storage.rpush(&key, vec![element]).unwrap(); | ||||
|                                     } | ||||
|                                 }); | ||||
|                                 tasks.push(task); | ||||
|                             } | ||||
|                              | ||||
|                             for task in tasks { | ||||
|                                 task.await.unwrap(); | ||||
|                             } | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     group.finish(); | ||||
| } | ||||
|  | ||||
| /// Benchmark concurrent scan operations | ||||
| fn bench_concurrent_scans(c: &mut Criterion) { | ||||
|     let mut group = c.benchmark_group("concurrent_ops/scans"); | ||||
|      | ||||
|     for num_clients in [10, 50] { | ||||
|         for backend_type in BackendType::all() { | ||||
|             // Pre-populate with data | ||||
|             let backend = setup_populated_backend(backend_type, 10_000, 100) | ||||
|                 .expect("Failed to setup backend"); | ||||
|             let storage = backend.storage.clone(); | ||||
|              | ||||
|             group.bench_with_input( | ||||
|                 BenchmarkId::new(format!("{}/clients", backend.name()), num_clients), | ||||
|                 &(storage, num_clients), | ||||
|                 |b, (storage, num_clients)| { | ||||
|                     let rt = Runtime::new().unwrap(); | ||||
|                     b.to_async(&rt).iter(|| { | ||||
|                         let storage = storage.clone(); | ||||
|                         let num_clients = *num_clients; | ||||
|                         async move { | ||||
|                             let mut tasks = Vec::new(); | ||||
|                              | ||||
|                             for _client_id in 0..num_clients { | ||||
|                                 let storage = storage.clone(); | ||||
|                                 let task = tokio::spawn(async move { | ||||
|                                     let mut cursor = 0u64; | ||||
|                                     let mut total = 0; | ||||
|                                     loop { | ||||
|                                         let (next_cursor, items) = storage | ||||
|                                             .scan(cursor, None, Some(100)) | ||||
|                                             .unwrap(); | ||||
|                                         total += items.len(); | ||||
|                                         if next_cursor == 0 { | ||||
|                                             break; | ||||
|                                         } | ||||
|                                         cursor = next_cursor; | ||||
|                                     } | ||||
|                                     total | ||||
|                                 }); | ||||
|                                 tasks.push(task); | ||||
|                             } | ||||
|                              | ||||
|                             for task in tasks { | ||||
|                                 task.await.unwrap(); | ||||
|                             } | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     group.finish(); | ||||
| } | ||||
|  | ||||
| criterion_group!( | ||||
|     benches, | ||||
|     bench_concurrent_writes, | ||||
|     bench_concurrent_reads, | ||||
|     bench_concurrent_mixed, | ||||
|     bench_concurrent_hash_ops, | ||||
|     bench_concurrent_list_ops, | ||||
|     bench_concurrent_scans, | ||||
| ); | ||||
|  | ||||
| criterion_main!(benches); | ||||
		Reference in New Issue
	
	Block a user