use chrono::Utc;
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use elif_orm::models::mapping_tests::{MockDatabaseRow, TestUser};
use serde_json::{json, Value};
use uuid::Uuid;
fn bench_hydration_approaches(c: &mut Criterion) {
let mut group = c.benchmark_group("hydration_comparison");
let user_id = Uuid::new_v4();
let now = Utc::now();
let mock_row = MockDatabaseRow::new()
.with_column("id", user_id.to_string())
.with_column("name", "John Doe")
.with_column("email", "john@example.com")
.with_column("age", 30)
.with_column("active", true)
.with_column("created_at", now.to_rfc3339())
.with_column("updated_at", Value::Null);
group.bench_function("json_based_hydration", |b| {
b.iter(|| {
let user: TestUser = TestUser::from_row(black_box(&mock_row)).unwrap();
black_box(user)
})
});
group.bench_function("direct_field_access", |b| {
b.iter(|| {
let user = TestUser {
id: black_box(user_id),
name: black_box("John Doe".to_string()),
email: black_box("john@example.com".to_string()),
age: black_box(Some(30)),
active: black_box(true),
created_at: black_box(now),
updated_at: black_box(None),
};
black_box(user)
})
});
for &count in &[10, 100, 1000] {
group.bench_with_input(
BenchmarkId::new("bulk_json_hydration", count),
&count,
|b, &count| {
let rows: Vec<_> = (0..count)
.map(|i| {
MockDatabaseRow::new()
.with_column("id", Uuid::new_v4().to_string())
.with_column("name", format!("User {}", i))
.with_column("email", format!("user{}@example.com", i))
.with_column("age", 20 + (i % 50))
.with_column("active", i % 2 == 0)
.with_column("created_at", now.to_rfc3339())
.with_column("updated_at", Value::Null)
})
.collect();
b.iter(|| {
let users: Result<Vec<TestUser>, _> = rows
.iter()
.map(|row| TestUser::from_row(black_box(row)))
.collect();
black_box(users.unwrap())
})
},
);
group.bench_with_input(
BenchmarkId::new("bulk_direct_access", count),
&count,
|b, &count| {
b.iter(|| {
let users: Vec<TestUser> = (0..count)
.map(|i| TestUser {
id: Uuid::new_v4(),
name: format!("User {}", i),
email: format!("user{}@example.com", i),
age: Some(20 + (i % 50)),
active: i % 2 == 0,
created_at: now,
updated_at: None,
})
.collect();
black_box(users)
})
},
);
}
group.finish();
}
fn bench_individual_field_access(c: &mut Criterion) {
let mut group = c.benchmark_group("field_access_patterns");
let mock_row = MockDatabaseRow::new()
.with_column("id", Uuid::new_v4().to_string())
.with_column("name", "John Doe")
.with_column("email", "john@example.com")
.with_column("age", 30)
.with_column("active", true);
group.bench_function("string_field_access", |b| {
b.iter(|| {
let name: String = mock_row.get(black_box("name")).unwrap();
black_box(name)
})
});
group.bench_function("integer_field_access", |b| {
b.iter(|| {
let age: i32 = mock_row.get(black_box("age")).unwrap();
black_box(age)
})
});
group.bench_function("boolean_field_access", |b| {
b.iter(|| {
let active: bool = mock_row.get(black_box("active")).unwrap();
black_box(active)
})
});
group.bench_function("optional_field_access", |b| {
b.iter(|| {
let age: Option<i32> = mock_row.try_get(black_box("age")).unwrap();
black_box(age)
})
});
group.finish();
}
fn bench_memory_allocation_patterns(c: &mut Criterion) {
let mut group = c.benchmark_group("memory_allocation");
group.bench_function("json_conversion_overhead", |b| {
let raw_value = json!("test_string");
b.iter(|| {
let db_value =
elif_orm::backends::DatabaseValue::from_json(black_box(raw_value.clone()));
let json_back = db_value.to_json();
let final_value: String = serde_json::from_value(json_back).unwrap();
black_box(final_value)
})
});
group.bench_function("direct_value_access", |b| {
b.iter(|| {
let value = black_box("test_string".to_string());
black_box(value)
})
});
group.finish();
}
criterion_group!(
benches,
bench_hydration_approaches,
bench_individual_field_access,
bench_memory_allocation_patterns
);
criterion_main!(benches);