benchmarking

This commit is contained in:
Maxime Van Hees
2025-10-30 11:17:26 +01:00
parent 592b6c1ea9
commit 9136e5f3c0
16 changed files with 3611 additions and 0 deletions

339
benches/scan_ops.rs Normal file
View File

@@ -0,0 +1,339 @@
// 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);