#![cfg(test)]
use std::sync::Arc;
use std::time::Instant;
use sz_orm_core::{Pool, PoolConfigBuilder, Value};
use sz_orm_sqlx::SqlitePoolHandle;
const SQLITE_URL: &str = "sqlite::memory:?cache=shared";
const ROW_COUNT: usize = 1000;
async fn create_pool() -> Pool {
let handle = Arc::new(
SqlitePoolHandle::connect(SQLITE_URL)
.await
.expect("SQLite connect failed"),
);
let factory = Arc::new(sz_orm_sqlx::SqlxSqliteConnectionFactory::new(handle));
let config = PoolConfigBuilder::new()
.max_size(10)
.min_idle(2)
.acquire_timeout(10)
.build()
.expect("PoolConfig invalid");
Pool::new(config, factory).expect("Pool::new failed")
}
async fn setup(pool: &Pool) {
let mut conn = pool.acquire().await.expect("acquire");
let _ = conn.execute("DROP TABLE IF EXISTS bench_sz_orm").await;
conn.execute(
"CREATE TABLE bench_sz_orm (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT NOT NULL, age INTEGER NOT NULL)",
)
.await
.expect("CREATE TABLE");
let sql = "INSERT INTO bench_sz_orm (name, email, age) VALUES (?, ?, ?)";
for i in 0..ROW_COUNT {
let name = format!("user_{}", i);
let email = format!("user_{}@test.com", i);
let age = (i % 100) as i64;
conn.execute_with_params(
sql,
&[Value::String(name), Value::String(email), Value::I64(age)],
)
.await
.expect("INSERT");
}
}
async fn teardown(pool: &Pool) {
let mut conn = pool.acquire().await.expect("acquire");
let _ = conn.execute("DROP TABLE IF EXISTS bench_sz_orm").await;
pool.close_all().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn sqlite_crud_benchmark() {
println!("=== SQLite in-memory CRUD Benchmark (sz-orm-sqlx) ===");
println!("数据量: {} 行", ROW_COUNT);
println!("连接: {}", SQLITE_URL);
println!();
let pool = create_pool().await;
setup(&pool).await;
println!("setup 完成: 表 bench_sz_orm 已插入 {} 行", ROW_COUNT);
let select_count = 100;
let start = Instant::now();
for i in 1..=select_count {
let mut conn = pool.acquire().await.expect("acquire");
let sql = "SELECT name, email, age FROM bench_sz_orm WHERE id = ?";
let rows = conn
.query_with_params(sql, &[Value::I64(i as i64)])
.await
.expect("query");
assert!(!rows.is_empty(), "SELECT BY ID should return 1 row");
}
let elapsed = start.elapsed();
let per_op = elapsed / select_count as u32;
println!(
"[SQLite] SELECT BY ID: {} 次查询总耗时 {:?}, 平均 {:?}/op",
select_count, elapsed, per_op
);
let start = Instant::now();
{
let mut conn = pool.acquire().await.expect("acquire");
let sql = "SELECT id, name, email, age FROM bench_sz_orm";
let rows = conn.query(sql).await.expect("query");
assert_eq!(rows.len(), ROW_COUNT, "SELECT ALL should return all rows");
}
let elapsed = start.elapsed();
println!(
"[SQLite] SELECT ALL HashMap ({}行): 总耗时 {:?}",
ROW_COUNT, elapsed
);
let start = Instant::now();
{
let mut conn = pool.acquire().await.expect("acquire");
let sql = "SELECT id, name, email, age FROM bench_sz_orm";
let (columns, values_matrix) = conn.query_values(sql).await.expect("query_values");
assert_eq!(
values_matrix.len(),
ROW_COUNT,
"SELECT ALL should return all rows"
);
assert_eq!(columns.len(), 4, "should have 4 columns");
}
let elapsed = start.elapsed();
println!(
"[SQLite] SELECT ALL Positional ({}行): 总耗时 {:?}",
ROW_COUNT, elapsed
);
let start = Instant::now();
for i in 1..=select_count {
let mut conn = pool.acquire().await.expect("acquire");
let sql = "SELECT name, email, age FROM bench_sz_orm WHERE id = ?";
let (_cols, values_matrix) = conn
.query_values_with_params(sql, &[Value::I64(i as i64)])
.await
.expect("query_values_with_params");
assert!(
!values_matrix.is_empty(),
"SELECT BY ID should return 1 row"
);
}
let elapsed = start.elapsed();
let per_op = elapsed / select_count as u32;
println!(
"[SQLite] SELECT BY ID Positional: {} 次查询总耗时 {:?}, 平均 {:?}/op",
select_count, elapsed, per_op
);
let update_count = 100;
let start = Instant::now();
for i in 1..=update_count {
let mut conn = pool.acquire().await.expect("acquire");
let sql = "UPDATE bench_sz_orm SET name = ? WHERE id = ?";
let new_name = format!("updated_{}", i);
conn.execute_with_params(sql, &[Value::String(new_name), Value::I64(i as i64)])
.await
.expect("update");
}
let elapsed = start.elapsed();
let per_op = elapsed / update_count as u32;
println!(
"[SQLite] UPDATE BY ID: {} 次更新总耗时 {:?}, 平均 {:?}/op",
update_count, elapsed, per_op
);
let delete_count = 100;
let start = Instant::now();
for i in 1..=delete_count {
let mut conn = pool.acquire().await.expect("acquire");
let sql = "DELETE FROM bench_sz_orm WHERE id = ?";
conn.execute_with_params(sql, &[Value::I64(i as i64)])
.await
.expect("delete");
}
let elapsed = start.elapsed();
let per_op = elapsed / delete_count as u32;
println!(
"[SQLite] DELETE BY ID: {} 次删除总耗时 {:?}, 平均 {:?}/op",
delete_count, elapsed, per_op
);
let insert_count = 100;
let start = Instant::now();
for i in 0..insert_count {
let mut conn = pool.acquire().await.expect("acquire");
let sql = "INSERT INTO bench_sz_orm (name, email, age) VALUES (?, ?, ?)";
let name = format!("new_user_{}", i);
let email = format!("new_user_{}@test.com", i);
let age = (i % 100) as i64;
conn.execute_with_params(
sql,
&[Value::String(name), Value::String(email), Value::I64(age)],
)
.await
.expect("insert");
}
let elapsed = start.elapsed();
let per_op = elapsed / insert_count as u32;
println!(
"[SQLite] INSERT: {} 次插入总耗时 {:?}, 平均 {:?}/op",
insert_count, elapsed, per_op
);
println!();
println!("=== SQLite in-memory CRUD Benchmark 完成 ===");
teardown(&pool).await;
}