| 5 | |
| 6 | #[tokio::test] |
| 7 | async fn test_fast_path_performance() -> Result<(), Box<dyn std::error::Error>> { |
| 8 | // Use a temporary file instead of in-memory database |
| 9 | let test_id = Uuid::new_v4().to_string().replace("-", ""); |
| 10 | let db_path = format!("/tmp/pgsqlite_test_{test_id}.db"); |
| 11 | |
| 12 | // Create database handler |
| 13 | let db_handler = Arc::new(DbHandler::new(&db_path)?); |
| 14 | |
| 15 | // Create a simple table without DECIMAL columns (should use fast path) |
| 16 | db_handler.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)").await?; |
| 17 | |
| 18 | // Warm up |
| 19 | for i in 0..10 { |
| 20 | db_handler.execute(&format!("INSERT INTO users (name, age) VALUES ('user{}', {})", i, i + 20)).await?; |
| 21 | } |
| 22 | |
| 23 | // Measure INSERT performance |
| 24 | let start = Instant::now(); |
| 25 | for i in 10..110 { |
| 26 | db_handler.execute(&format!("INSERT INTO users (name, age) VALUES ('user{}', {})", i, i + 20)).await?; |
| 27 | } |
| 28 | let insert_duration = start.elapsed(); |
| 29 | println!("100 INSERTs took: {:?} ({:.3}ms per insert)", insert_duration, insert_duration.as_secs_f64() * 1000.0 / 100.0); |
| 30 | |
| 31 | // Measure SELECT performance |
| 32 | let start = Instant::now(); |
| 33 | for _ in 0..100 { |
| 34 | let result = db_handler.query("SELECT * FROM users WHERE age > 25").await?; |
| 35 | assert!(!result.rows.is_empty()); |
| 36 | } |
| 37 | let select_duration = start.elapsed(); |
| 38 | println!("100 SELECTs took: {:?} ({:.3}ms per select)", select_duration, select_duration.as_secs_f64() * 1000.0 / 100.0); |
| 39 | |
| 40 | // Now test with DECIMAL table (should NOT use fast path) |
| 41 | db_handler.execute("CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, price DECIMAL(10,2))").await?; |
| 42 | |
| 43 | let start = Instant::now(); |
| 44 | for i in 0..100 { |
| 45 | db_handler.execute(&format!("INSERT INTO products (name, price) VALUES ('product{i}', {i}.99)")).await?; |
| 46 | } |
| 47 | let decimal_insert_duration = start.elapsed(); |
| 48 | println!("100 DECIMAL INSERTs took: {:?} ({:.3}ms per insert)", decimal_insert_duration, decimal_insert_duration.as_secs_f64() * 1000.0 / 100.0); |
| 49 | |
| 50 | // Fast path should generally be faster, but with our optimized implementation |
| 51 | // the difference might be small. Log the results for analysis. |
| 52 | if insert_duration >= decimal_insert_duration { |
| 53 | println!("WARNING: Fast path INSERT ({insert_duration:?}) was not faster than decimal path ({decimal_insert_duration:?})"); |
| 54 | } |
| 55 | |
| 56 | // Clean up |
| 57 | drop(db_handler); |
| 58 | let _ = std::fs::remove_file(&db_path); |
| 59 | let _ = std::fs::remove_file(format!("{db_path}-journal")); |
| 60 | let _ = std::fs::remove_file(format!("{db_path}-wal")); |
| 61 | let _ = std::fs::remove_file(format!("{db_path}-shm")); |
| 62 | |
| 63 | Ok(()) |
| 64 | } |