Experiment 051: Lock-free reader pool with atomics
Date: 2026-04-15
Status: Rejected (not attempted — optimization target is dead code)
Problem
The reader pool uses sqlite3_mutex_enter/leave around a linear scan of up to 16 reader slots in acquire_reader (resqlite.c:891). Under contention (8 concurrent reads), the mutex serializes pool acquisition. A lock-free approach using atomic_compare_exchange_weak on in_use flags could eliminate the mutex overhead (~20-25ns per lock/unlock pair on ARM64 vs ~3-5ns for a CAS).
Why Not Attempted
Cross-referencing with experiment 030 (dedicated reader assignment) revealed that the mutex path is dead code in the current architecture. Each Dart reader worker isolate calls resqlite_stmt_acquire_on(reader_id) which bypasses acquire_reader entirely — no mutex, no pool scan. The generic resqlite_stmt_acquire (with mutex) is only used by resqlite_db_status_total (a diagnostic function) and as a fallback path that the Dart code never takes.
Experiment 030 already solved the contention problem at a higher level: by assigning dedicated readers to workers, it eliminated per-query pool coordination entirely. Making the unused pool path lock-free would be dead-code optimization.
Decision
Rejected — not attempted. The optimization target doesn't exist in the live code path. The pool_mutex could be removed entirely in a cleanup pass, but that's a code quality change, not a performance experiment.
This was also a good lesson in cross-referencing existing experiments before implementation. A quick check of 030 saved hours of work that would have shown no benchmark signal.