| 72 | /// Test lock contention with multiple async tasks |
| 73 | #[tokio::test] |
| 74 | async fn benchmark_async_contention() { |
| 75 | eprintln!("\n=== Async Contention Benchmark ==="); |
| 76 | |
| 77 | let db_handler = Arc::new(DbHandler::new(":memory:").unwrap()); |
| 78 | |
| 79 | // Setup test data |
| 80 | db_handler.execute(" |
| 81 | CREATE TABLE contention_test ( |
| 82 | id INTEGER PRIMARY KEY, |
| 83 | value INTEGER |
| 84 | ) |
| 85 | ").await.expect("Failed to create table"); |
| 86 | |
| 87 | for i in 0..100 { |
| 88 | db_handler.execute(&format!( |
| 89 | "INSERT INTO contention_test (id, value) VALUES ({}, {})", |
| 90 | i, i * 10 |
| 91 | )).await.expect("Failed to insert"); |
| 92 | } |
| 93 | |
| 94 | let task_counts = vec![1, 2, 4, 8]; |
| 95 | let iterations_per_task = 25; |
| 96 | |
| 97 | for task_count in task_counts { |
| 98 | let start_time = Instant::now(); |
| 99 | let mut handles = Vec::new(); |
| 100 | |
| 101 | for task_id in 0..task_count { |
| 102 | let db_handler = db_handler.clone(); |
| 103 | let handle = tokio::spawn(async move { |
| 104 | let mut task_times = Vec::new(); |
| 105 | |
| 106 | for i in 0..iterations_per_task { |
| 107 | let query_start = Instant::now(); |
| 108 | let id = (task_id * iterations_per_task + i) % 100; |
| 109 | |
| 110 | let result = db_handler.query( |
| 111 | &format!("SELECT * FROM contention_test WHERE id = {}", id) |
| 112 | ).await.expect("Query failed"); |
| 113 | |
| 114 | assert!(!result.rows.is_empty()); |
| 115 | task_times.push(query_start.elapsed()); |
| 116 | } |
| 117 | |
| 118 | task_times |
| 119 | }); |
| 120 | |
| 121 | handles.push(handle); |
| 122 | } |
| 123 | |
| 124 | // Wait for all tasks |
| 125 | let mut all_times = Vec::new(); |
| 126 | for handle in handles { |
| 127 | let times = handle.await.expect("Task failed"); |
| 128 | all_times.extend(times); |
| 129 | } |
| 130 | |
| 131 | let total_duration = start_time.elapsed(); |