use criterion::{Criterion, criterion_group, criterion_main};
use std::sync::Arc;
use tokio::runtime::Runtime;
use fred::prelude::*; use redis::aio::MultiplexedConnection; use rustis::{client::Client as RustisClient, commands::StringCommands};
async fn setup_data(client: &RustisClient) {
let data: Vec<_> = (0..100)
.map(|i| (format!("key{i}"), format!("value{i}")))
.collect();
let _: () = client.mset(data).await.unwrap();
}
async fn bench_rustis(client: RustisClient, tasks: usize, reqs: usize, keys: Arc<Vec<String>>) {
let mut handles = vec![];
for _ in 0..tasks {
let client = client.clone();
let keys = keys.clone();
handles.push(tokio::spawn(async move {
for i in 0..reqs {
let _: String = rustis::commands::StringCommands::get(&client, &keys[i % 100])
.await
.unwrap();
}
}));
}
for h in handles {
let _ = h.await;
}
}
async fn bench_fred(
client: fred::clients::Client,
tasks: usize,
reqs: usize,
keys: Arc<Vec<String>>,
) {
let mut handles = vec![];
for _ in 0..tasks {
let client = client.clone();
let keys = keys.clone();
handles.push(tokio::spawn(async move {
for i in 0..reqs {
let _: String = client.get(&keys[i % 100]).await.unwrap();
}
}));
}
for h in handles {
let _ = h.await;
}
}
async fn bench_redis_rs(
conn: MultiplexedConnection,
tasks: usize,
reqs: usize,
keys: Arc<Vec<String>>,
) {
let mut handles = vec![];
for _ in 0..tasks {
let mut conn = conn.clone();
let keys = keys.clone();
handles.push(tokio::spawn(async move {
for i in 0..reqs {
let _: String = redis::cmd("GET")
.arg(&keys[i % 100])
.query_async(&mut conn)
.await
.unwrap();
}
}));
}
for h in handles {
let _ = h.await;
}
}
fn compare_drivers(c: &mut Criterion) {
let rt = Runtime::new().unwrap();
let keys: Arc<Vec<String>> = Arc::new((0..100).map(|i| format!("key{i}")).collect());
let redis_host = std::env::var("REDIS_HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
let (rustis, fred, redis_rs) = rt.block_on(async {
let rustis = RustisClient::connect(redis_host.clone()).await.unwrap();
setup_data(&rustis).await;
let config = Config::from_url(&format!("redis://{redis_host}:6379/0")).unwrap();
let fred = Builder::from_config(config).build().unwrap();
fred.init().await.unwrap();
let redis_rs = redis::Client::open(format!("redis://{redis_host}:6379")).unwrap();
let redis_rs = redis_rs.get_multiplexed_async_connection().await.unwrap();
(rustis, fred, redis_rs)
});
let mut group = c.benchmark_group("Multiplexing Comparison");
let num_tasks = 12;
let reqs_per_task = 200;
group.bench_function("rustis", |b| {
b.to_async(&rt)
.iter(|| bench_rustis(rustis.clone(), num_tasks, reqs_per_task, keys.clone()));
});
group.bench_function("fred", |b| {
b.to_async(&rt)
.iter(|| bench_fred(fred.clone(), num_tasks, reqs_per_task, keys.clone()));
});
group.bench_function("redis-rs", |b| {
b.to_async(&rt)
.iter(|| bench_redis_rs(redis_rs.clone(), num_tasks, reqs_per_task, keys.clone()));
});
group.finish();
}
criterion_group!(benches, compare_drivers);
criterion_main!(benches);