339 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			339 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| // benches/scan_ops.rs
 | |
| use criterion::{criterion_group, criterion_main, Criterion, BenchmarkId};
 | |
| 
 | |
| mod common;
 | |
| use common::*;
 | |
| 
 | |
| /// Benchmark SCAN operation - full database scan
 | |
| fn bench_scan_full(c: &mut Criterion) {
 | |
|     let mut group = c.benchmark_group("scan_ops/scan_full");
 | |
|     
 | |
|     for size in [1_000, 10_000] {
 | |
|         for backend_type in BackendType::all() {
 | |
|             let backend = setup_populated_backend(backend_type, size, 100)
 | |
|                 .expect("Failed to setup backend");
 | |
|             
 | |
|             group.bench_with_input(
 | |
|                 BenchmarkId::new(format!("{}/size", backend.name()), size),
 | |
|                 &backend,
 | |
|                 |b, backend| {
 | |
|                     b.iter(|| {
 | |
|                         let mut cursor = 0u64;
 | |
|                         let mut total = 0;
 | |
|                         loop {
 | |
|                             let (next_cursor, items) = backend.storage
 | |
|                                 .scan(cursor, None, Some(100))
 | |
|                                 .unwrap();
 | |
|                             total += items.len();
 | |
|                             if next_cursor == 0 {
 | |
|                                 break;
 | |
|                             }
 | |
|                             cursor = next_cursor;
 | |
|                         }
 | |
|                         total
 | |
|                     });
 | |
|                 }
 | |
|             );
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     group.finish();
 | |
| }
 | |
| 
 | |
| /// Benchmark SCAN operation with pattern matching
 | |
| fn bench_scan_pattern(c: &mut Criterion) {
 | |
|     let mut group = c.benchmark_group("scan_ops/scan_pattern");
 | |
|     
 | |
|     for backend_type in BackendType::all() {
 | |
|         // Create backend with mixed key patterns
 | |
|         let backend = BenchmarkBackend::new(backend_type).expect("Failed to create backend");
 | |
|         let mut generator = DataGenerator::new(42);
 | |
|         
 | |
|         // Insert keys with different patterns
 | |
|         for i in 0..3_000 {
 | |
|             let key = if i < 1_000 {
 | |
|                 format!("user:{}:profile", i)
 | |
|             } else if i < 2_000 {
 | |
|                 format!("session:{}:data", i - 1_000)
 | |
|             } else {
 | |
|                 format!("cache:{}:value", i - 2_000)
 | |
|             };
 | |
|             let value = generator.generate_value(100);
 | |
|             backend.storage.set(key, value).unwrap();
 | |
|         }
 | |
|         
 | |
|         // Benchmark pattern matching
 | |
|         for pattern in ["user:*", "session:*", "cache:*"] {
 | |
|             group.bench_with_input(
 | |
|                 BenchmarkId::new(format!("{}/pattern", backend.name()), pattern),
 | |
|                 &(backend.storage.clone(), pattern),
 | |
|                 |b, (storage, pattern)| {
 | |
|                     b.iter(|| {
 | |
|                         let mut cursor = 0u64;
 | |
|                         let mut total = 0;
 | |
|                         loop {
 | |
|                             let (next_cursor, items) = storage
 | |
|                                 .scan(cursor, Some(pattern), Some(100))
 | |
|                                 .unwrap();
 | |
|                             total += items.len();
 | |
|                             if next_cursor == 0 {
 | |
|                                 break;
 | |
|                             }
 | |
|                             cursor = next_cursor;
 | |
|                         }
 | |
|                         total
 | |
|                     });
 | |
|                 }
 | |
|             );
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     group.finish();
 | |
| }
 | |
| 
 | |
| /// Benchmark HSCAN operation - scan hash fields
 | |
| fn bench_hscan(c: &mut Criterion) {
 | |
|     let mut group = c.benchmark_group("scan_ops/hscan");
 | |
|     
 | |
|     for fields_count in [10, 100] {
 | |
|         for backend_type in BackendType::all() {
 | |
|             let backend = setup_populated_backend_hashes(backend_type, 100, fields_count, 100)
 | |
|                 .expect("Failed to setup backend");
 | |
|             let generator = DataGenerator::new(42);
 | |
|             let key = generator.generate_key("bench:hash", 0);
 | |
|             
 | |
|             group.bench_with_input(
 | |
|                 BenchmarkId::new(format!("{}/fields", backend.name()), fields_count),
 | |
|                 &(backend, key),
 | |
|                 |b, (backend, key)| {
 | |
|                     b.iter(|| {
 | |
|                         let mut cursor = 0u64;
 | |
|                         let mut total = 0;
 | |
|                         loop {
 | |
|                             let (next_cursor, items) = backend.storage
 | |
|                                 .hscan(key, cursor, None, Some(10))
 | |
|                                 .unwrap();
 | |
|                             total += items.len();
 | |
|                             if next_cursor == 0 {
 | |
|                                 break;
 | |
|                             }
 | |
|                             cursor = next_cursor;
 | |
|                         }
 | |
|                         total
 | |
|                     });
 | |
|                 }
 | |
|             );
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     group.finish();
 | |
| }
 | |
| 
 | |
| /// Benchmark HSCAN with pattern matching
 | |
| fn bench_hscan_pattern(c: &mut Criterion) {
 | |
|     let mut group = c.benchmark_group("scan_ops/hscan_pattern");
 | |
|     
 | |
|     for backend_type in BackendType::all() {
 | |
|         let backend = BenchmarkBackend::new(backend_type).expect("Failed to create backend");
 | |
|         let mut generator = DataGenerator::new(42);
 | |
|         
 | |
|         // Create a hash with mixed field patterns
 | |
|         let key = "bench:hash:0".to_string();
 | |
|         let mut fields = Vec::new();
 | |
|         for i in 0..100 {
 | |
|             let field = if i < 33 {
 | |
|                 format!("user_{}", i)
 | |
|             } else if i < 66 {
 | |
|                 format!("session_{}", i - 33)
 | |
|             } else {
 | |
|                 format!("cache_{}", i - 66)
 | |
|             };
 | |
|             let value = generator.generate_value(100);
 | |
|             fields.push((field, value));
 | |
|         }
 | |
|         backend.storage.hset(&key, fields).unwrap();
 | |
|         
 | |
|         // Benchmark pattern matching
 | |
|         for pattern in ["user_*", "session_*", "cache_*"] {
 | |
|             group.bench_with_input(
 | |
|                 BenchmarkId::new(format!("{}/pattern", backend.name()), pattern),
 | |
|                 &(backend.storage.clone(), key.clone(), pattern),
 | |
|                 |b, (storage, key, pattern)| {
 | |
|                     b.iter(|| {
 | |
|                         let mut cursor = 0u64;
 | |
|                         let mut total = 0;
 | |
|                         loop {
 | |
|                             let (next_cursor, items) = storage
 | |
|                                 .hscan(key, cursor, Some(pattern), Some(10))
 | |
|                                 .unwrap();
 | |
|                             total += items.len();
 | |
|                             if next_cursor == 0 {
 | |
|                                 break;
 | |
|                             }
 | |
|                             cursor = next_cursor;
 | |
|                         }
 | |
|                         total
 | |
|                     });
 | |
|                 }
 | |
|             );
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     group.finish();
 | |
| }
 | |
| 
 | |
| /// Benchmark KEYS operation with various patterns
 | |
| fn bench_keys_operation(c: &mut Criterion) {
 | |
|     let mut group = c.benchmark_group("scan_ops/keys");
 | |
|     
 | |
|     for backend_type in BackendType::all() {
 | |
|         // Create backend with mixed key patterns
 | |
|         let backend = BenchmarkBackend::new(backend_type).expect("Failed to create backend");
 | |
|         let mut generator = DataGenerator::new(42);
 | |
|         
 | |
|         // Insert keys with different patterns
 | |
|         for i in 0..3_000 {
 | |
|             let key = if i < 1_000 {
 | |
|                 format!("user:{}:profile", i)
 | |
|             } else if i < 2_000 {
 | |
|                 format!("session:{}:data", i - 1_000)
 | |
|             } else {
 | |
|                 format!("cache:{}:value", i - 2_000)
 | |
|             };
 | |
|             let value = generator.generate_value(100);
 | |
|             backend.storage.set(key, value).unwrap();
 | |
|         }
 | |
|         
 | |
|         // Benchmark different patterns
 | |
|         for pattern in ["*", "user:*", "session:*", "*:profile", "user:*:profile"] {
 | |
|             group.bench_with_input(
 | |
|                 BenchmarkId::new(format!("{}/pattern", backend.name()), pattern),
 | |
|                 &(backend.storage.clone(), pattern),
 | |
|                 |b, (storage, pattern)| {
 | |
|                     b.iter(|| {
 | |
|                         storage.keys(pattern).unwrap()
 | |
|                     });
 | |
|                 }
 | |
|             );
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     group.finish();
 | |
| }
 | |
| 
 | |
| /// Benchmark DBSIZE operation
 | |
| fn bench_dbsize(c: &mut Criterion) {
 | |
|     let mut group = c.benchmark_group("scan_ops/dbsize");
 | |
|     
 | |
|     for size in [1_000, 10_000] {
 | |
|         for backend_type in BackendType::all() {
 | |
|             let backend = setup_populated_backend(backend_type, size, 100)
 | |
|                 .expect("Failed to setup backend");
 | |
|             
 | |
|             group.bench_with_input(
 | |
|                 BenchmarkId::new(format!("{}/size", backend.name()), size),
 | |
|                 &backend,
 | |
|                 |b, backend| {
 | |
|                     b.iter(|| {
 | |
|                         backend.storage.dbsize().unwrap()
 | |
|                     });
 | |
|                 }
 | |
|             );
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     group.finish();
 | |
| }
 | |
| 
 | |
| /// Benchmark LRANGE with different range sizes
 | |
| fn bench_lrange_sizes(c: &mut Criterion) {
 | |
|     let mut group = c.benchmark_group("scan_ops/lrange");
 | |
|     
 | |
|     for range_size in [10, 50, 100] {
 | |
|         for backend_type in BackendType::all() {
 | |
|             let backend = setup_populated_backend_lists(backend_type, 100, 100, 100)
 | |
|                 .expect("Failed to setup backend");
 | |
|             let generator = DataGenerator::new(42);
 | |
|             let key = generator.generate_key("bench:list", 0);
 | |
|             
 | |
|             group.bench_with_input(
 | |
|                 BenchmarkId::new(format!("{}/range", backend.name()), range_size),
 | |
|                 &(backend, key, range_size),
 | |
|                 |b, (backend, key, range_size)| {
 | |
|                     b.iter(|| {
 | |
|                         backend.storage.lrange(key, 0, (*range_size - 1) as i64).unwrap()
 | |
|                     });
 | |
|                 }
 | |
|             );
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     group.finish();
 | |
| }
 | |
| 
 | |
| /// Benchmark HKEYS operation
 | |
| fn bench_hkeys(c: &mut Criterion) {
 | |
|     let mut group = c.benchmark_group("scan_ops/hkeys");
 | |
|     
 | |
|     for fields_count in [10, 50, 100] {
 | |
|         for backend_type in BackendType::all() {
 | |
|             let backend = setup_populated_backend_hashes(backend_type, 100, fields_count, 100)
 | |
|                 .expect("Failed to setup backend");
 | |
|             let generator = DataGenerator::new(42);
 | |
|             let key = generator.generate_key("bench:hash", 0);
 | |
|             
 | |
|             group.bench_with_input(
 | |
|                 BenchmarkId::new(format!("{}/fields", backend.name()), fields_count),
 | |
|                 &(backend, key),
 | |
|                 |b, (backend, key)| {
 | |
|                     b.iter(|| {
 | |
|                         backend.storage.hkeys(key).unwrap()
 | |
|                     });
 | |
|                 }
 | |
|             );
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     group.finish();
 | |
| }
 | |
| 
 | |
| /// Benchmark HVALS operation
 | |
| fn bench_hvals(c: &mut Criterion) {
 | |
|     let mut group = c.benchmark_group("scan_ops/hvals");
 | |
|     
 | |
|     for fields_count in [10, 50, 100] {
 | |
|         for backend_type in BackendType::all() {
 | |
|             let backend = setup_populated_backend_hashes(backend_type, 100, fields_count, 100)
 | |
|                 .expect("Failed to setup backend");
 | |
|             let generator = DataGenerator::new(42);
 | |
|             let key = generator.generate_key("bench:hash", 0);
 | |
|             
 | |
|             group.bench_with_input(
 | |
|                 BenchmarkId::new(format!("{}/fields", backend.name()), fields_count),
 | |
|                 &(backend, key),
 | |
|                 |b, (backend, key)| {
 | |
|                     b.iter(|| {
 | |
|                         backend.storage.hvals(key).unwrap()
 | |
|                     });
 | |
|                 }
 | |
|             );
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     group.finish();
 | |
| }
 | |
| 
 | |
| criterion_group!(
 | |
|     benches,
 | |
|     bench_scan_full,
 | |
|     bench_scan_pattern,
 | |
|     bench_hscan,
 | |
|     bench_hscan_pattern,
 | |
|     bench_keys_operation,
 | |
|     bench_dbsize,
 | |
|     bench_lrange_sizes,
 | |
|     bench_hkeys,
 | |
|     bench_hvals,
 | |
| );
 | |
| 
 | |
| criterion_main!(benches); |