use criterion::{black_box, criterion_group, criterion_main, Criterion};
use sqlx::postgres::Postgres;
fn pt_encode<T: resolute::Encode>(val: &T, buf: &mut bytes::BytesMut) {
resolute::Encode::encode(val, buf);
}
fn pt_decode<T: resolute::Decode>(buf: &[u8]) -> T {
T::decode(buf).unwrap()
}
fn sqlx_encode<'q, T: sqlx::Encode<'q, Postgres>>(
val: T,
buf: &mut sqlx::postgres::PgArgumentBuffer,
) {
let _ = sqlx::Encode::<Postgres>::encode(val, buf);
}
fn bench_encode_i32(c: &mut Criterion) {
let mut group = c.benchmark_group("encode_i32");
group.bench_function("resolute", |b| {
let mut buf = bytes::BytesMut::with_capacity(64);
b.iter(|| {
buf.clear();
pt_encode(&42i32, &mut buf);
black_box(&buf);
});
});
group.bench_function("sqlx", |b| {
b.iter(|| {
let mut buf = sqlx::postgres::PgArgumentBuffer::default();
sqlx_encode(black_box(42i32), &mut buf);
black_box(&buf);
});
});
group.finish();
}
fn bench_decode_i32(c: &mut Criterion) {
let mut buf = bytes::BytesMut::new();
pt_encode(&42i32, &mut buf);
let bytes = buf.freeze();
c.bench_function("decode_i32/resolute", |b| {
b.iter(|| black_box(pt_decode::<i32>(&bytes)));
});
}
fn bench_encode_i64(c: &mut Criterion) {
let mut group = c.benchmark_group("encode_i64");
group.bench_function("resolute", |b| {
let mut buf = bytes::BytesMut::with_capacity(64);
b.iter(|| {
buf.clear();
pt_encode(&123456789012345i64, &mut buf);
black_box(&buf);
});
});
group.bench_function("sqlx", |b| {
b.iter(|| {
let mut buf = sqlx::postgres::PgArgumentBuffer::default();
sqlx_encode(black_box(123456789012345i64), &mut buf);
black_box(&buf);
});
});
group.finish();
}
fn bench_decode_i64(c: &mut Criterion) {
let mut buf = bytes::BytesMut::new();
pt_encode(&123456789012345i64, &mut buf);
let bytes = buf.freeze();
c.bench_function("decode_i64/resolute", |b| {
b.iter(|| black_box(pt_decode::<i64>(&bytes)));
});
}
fn bench_encode_string(c: &mut Criterion) {
let mut group = c.benchmark_group("encode_string_39b");
let s = "hello world, this is a benchmark string";
group.bench_function("resolute", |b| {
let mut buf = bytes::BytesMut::with_capacity(128);
b.iter(|| {
buf.clear();
pt_encode(&s, &mut buf);
black_box(&buf);
});
});
group.bench_function("sqlx", |b| {
b.iter(|| {
let mut buf = sqlx::postgres::PgArgumentBuffer::default();
sqlx_encode(black_box(s), &mut buf);
black_box(&buf);
});
});
group.finish();
}
fn bench_decode_string(c: &mut Criterion) {
let s = "hello world, this is a benchmark string";
let mut buf = bytes::BytesMut::new();
pt_encode(&s.to_string(), &mut buf);
let bytes = buf.freeze();
c.bench_function("decode_string_39b/resolute", |b| {
b.iter(|| black_box(pt_decode::<String>(&bytes)));
});
}
fn bench_encode_uuid(c: &mut Criterion) {
let mut group = c.benchmark_group("encode_uuid");
let id = uuid::Uuid::new_v4();
group.bench_function("resolute", |b| {
let mut buf = bytes::BytesMut::with_capacity(32);
b.iter(|| {
buf.clear();
pt_encode(&id, &mut buf);
black_box(&buf);
});
});
group.bench_function("sqlx", |b| {
b.iter(|| {
let mut buf = sqlx::postgres::PgArgumentBuffer::default();
sqlx_encode(black_box(id), &mut buf);
black_box(&buf);
});
});
group.finish();
}
fn bench_decode_uuid(c: &mut Criterion) {
let id = uuid::Uuid::new_v4();
let mut buf = bytes::BytesMut::new();
pt_encode(&id, &mut buf);
let bytes = buf.freeze();
c.bench_function("decode_uuid/resolute", |b| {
b.iter(|| black_box(pt_decode::<uuid::Uuid>(&bytes)));
});
}
fn bench_encode_timestamp(c: &mut Criterion) {
let mut group = c.benchmark_group("encode_timestamptz");
let ts = chrono::Utc::now();
group.bench_function("resolute", |b| {
let mut buf = bytes::BytesMut::with_capacity(32);
b.iter(|| {
buf.clear();
pt_encode(&ts, &mut buf);
black_box(&buf);
});
});
group.bench_function("sqlx", |b| {
b.iter(|| {
let mut buf = sqlx::postgres::PgArgumentBuffer::default();
sqlx_encode(black_box(ts), &mut buf);
black_box(&buf);
});
});
group.finish();
}
fn bench_decode_timestamp(c: &mut Criterion) {
let ts = chrono::Utc::now();
let mut buf = bytes::BytesMut::new();
pt_encode(&ts, &mut buf);
let bytes = buf.freeze();
c.bench_function("decode_timestamptz/resolute", |b| {
b.iter(|| black_box(pt_decode::<chrono::DateTime<chrono::Utc>>(&bytes)));
});
}
fn bench_encode_jsonb(c: &mut Criterion) {
let mut group = c.benchmark_group("encode_jsonb");
let val = serde_json::json!({"key": "value", "num": 42, "arr": [1,2,3]});
group.bench_function("resolute", |b| {
let mut buf = bytes::BytesMut::with_capacity(256);
b.iter(|| {
buf.clear();
pt_encode(&val, &mut buf);
black_box(&buf);
});
});
group.bench_function("sqlx", |b| {
b.iter(|| {
let mut buf = sqlx::postgres::PgArgumentBuffer::default();
sqlx_encode(sqlx::types::Json(black_box(&val)), &mut buf);
black_box(&buf);
});
});
group.finish();
}
fn bench_named_param_rewrite(c: &mut Criterion) {
let sql = "SELECT * FROM users WHERE org_id = :org_id AND name = :name AND active = :active AND created > :since ORDER BY :name";
c.bench_function("named_param_rewrite_4params", |b| {
b.iter(|| {
black_box(resolute::named_params::rewrite(black_box(sql)));
});
});
}
criterion_group!(
benches,
bench_encode_i32,
bench_decode_i32,
bench_encode_i64,
bench_decode_i64,
bench_encode_string,
bench_decode_string,
bench_encode_uuid,
bench_decode_uuid,
bench_encode_timestamp,
bench_decode_timestamp,
bench_encode_jsonb,
bench_named_param_rewrite,
);
criterion_main!(benches);