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); |