use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use elif_orm::database::{DatabasePool, PoolConfig};
use std::time::Duration;
use tokio::runtime::Runtime;
async fn bench_pool_acquisition(pool: &DatabasePool, operations: usize) {
for _ in 0..operations {
if let Ok(conn) = pool.acquire().await {
let _ = black_box(conn);
}
}
}
fn bench_pool_creation(c: &mut Criterion) {
let rt = Runtime::new().unwrap();
let mut group = c.benchmark_group("pool_creation");
for &max_connections in &[5, 10, 20, 50] {
group.bench_with_input(
BenchmarkId::new("create_pool", max_connections),
&max_connections,
|b, &max_connections| {
b.iter(|| {
rt.block_on(async {
let config = PoolConfig::builder()
.max_connections(black_box(max_connections))
.min_connections(black_box(1))
.connection_timeout(Duration::from_secs(30))
.build_with_defaults();
black_box(config)
})
})
},
);
}
group.finish();
}
fn bench_pool_config_builder(c: &mut Criterion) {
let mut group = c.benchmark_group("pool_config_builder");
group.bench_function("simple_config", |b| {
b.iter(|| {
let config = PoolConfig::builder()
.max_connections(black_box(20))
.build_with_defaults();
black_box(config)
})
});
group.bench_function("complex_config", |b| {
b.iter(|| {
let config = PoolConfig::builder()
.max_connections(black_box(50))
.min_connections(black_box(5))
.connection_timeout(Duration::from_secs(black_box(30)))
.idle_timeout(Duration::from_secs(black_box(600)))
.max_lifetime(Duration::from_secs(black_box(3600)))
.test_before_acquire(black_box(true))
.build_with_defaults();
black_box(config)
})
});
group.finish();
}
#[derive(Clone)]
struct MockPool {
max_connections: usize,
current_connections: std::sync::Arc<std::sync::atomic::AtomicUsize>,
}
impl MockPool {
fn new(max_connections: usize) -> Self {
Self {
max_connections,
current_connections: std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0)),
}
}
async fn acquire(&self) -> Result<MockConnection, String> {
use std::sync::atomic::Ordering;
let current = self.current_connections.fetch_add(1, Ordering::SeqCst);
if current >= self.max_connections {
self.current_connections.fetch_sub(1, Ordering::SeqCst);
return Err("Pool exhausted".to_string());
}
tokio::time::sleep(Duration::from_micros(100)).await;
Ok(MockConnection { pool: self.clone() })
}
}
struct MockConnection {
pool: MockPool,
}
impl Drop for MockConnection {
fn drop(&mut self) {
self.pool
.current_connections
.fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
}
}
fn bench_mock_pool_operations(c: &mut Criterion) {
let rt = Runtime::new().unwrap();
let mut group = c.benchmark_group("mock_pool_operations");
for &pool_size in &[5, 10, 20] {
group.bench_with_input(
BenchmarkId::new("sequential_acquisition", pool_size),
&pool_size,
|b, &pool_size| {
let pool = MockPool::new(pool_size);
b.iter(|| {
rt.block_on(async {
let mut connections = Vec::new();
for _ in 0..pool_size {
if let Ok(conn) = pool.acquire().await {
connections.push(conn);
}
}
black_box(connections)
})
})
},
);
}
for &concurrency in &[2, 5, 10] {
group.bench_with_input(
BenchmarkId::new("concurrent_acquisition", concurrency),
&concurrency,
|b, &concurrency| {
let pool = MockPool::new(20);
b.iter(|| {
rt.block_on(async {
let handles: Vec<_> = (0..concurrency)
.map(|_| {
let pool = pool.clone();
tokio::spawn(async move {
let mut connections = Vec::new();
for _ in 0..5 {
if let Ok(conn) = pool.acquire().await {
connections.push(conn);
}
tokio::time::sleep(Duration::from_micros(10)).await;
}
black_box(connections)
})
})
.collect();
for handle in handles {
handle.await.unwrap();
}
})
})
},
);
}
group.finish();
}
fn bench_pool_stress_patterns(c: &mut Criterion) {
let rt = Runtime::new().unwrap();
let mut group = c.benchmark_group("pool_stress_patterns");
group.bench_function("rapid_acquire_release", |b| {
let pool = MockPool::new(10);
b.iter(|| {
rt.block_on(async {
for _ in 0..50 {
if let Ok(conn) = pool.acquire().await {
let _ = black_box(conn);
}
}
})
})
});
group.bench_function("mixed_hold_times", |b| {
let pool = MockPool::new(15);
b.iter(|| {
rt.block_on(async {
let mut long_lived = Vec::new();
for i in 0..5 {
if let Ok(conn) = pool.acquire().await {
if i % 2 == 0 {
long_lived.push(conn);
}
}
}
for _ in 0..20 {
if let Ok(conn) = pool.acquire().await {
let _ = black_box(conn);
}
}
black_box(long_lived)
})
})
});
group.finish();
}
criterion_group!(
benches,
bench_pool_creation,
bench_pool_config_builder,
bench_mock_pool_operations,
bench_pool_stress_patterns
);
criterion_main!(benches);