fix(core): teach connection pools to pool their resources - #774
Open
cds-amal wants to merge 5 commits into
Open
Conversation
- Count pools and SQLite connections: created, dropped, live, and peak.
- Instrument r2d2 directly so deltas are exact, assertable, and
portable.
- Add an ignored census workload covering sequential, concurrent, and
drop costs.
- Baseline: 10 idle surfnets open 100 connections and keep 10 pools,
each with a private 3-thread scheduler.
- Census is temporary branch instrumentation and is removed by the final
commit.
Run alone because counters are process-global:
cargo test -p surfpool-core --lib storage::census -- \
--ignored --nocapture --test-threads=1
- Share one process-wide r2d2 scheduler across SQLite and Postgres pools. - Remove the default 3-thread scheduler cost per pool. - Preserve pooling behavior, limits, and connection lifetimes. - Dropped pools are not retained; r2d2 reap jobs hold only weak references. - Before solana-foundation#759: up to 8,316 threads, 96% `r2d2-worker`. - After: 3 `r2d2-worker` threads across the full core test suite.
- Set SQLite `min_idle` to 1, matching Postgres. - Avoid opening 10 connections per surfnet before any query runs. - Keep `max_size` at 10 and grow on demand.
- Apply `busy_timeout` before setup can encounter SQLite locks. - Prevent on-demand pool growth from discarding connections on transient contention. - Eliminate observed `database is locked` churn. - Census: 53 opens / 36 survivors -> 20 opens / 20 survivors on macOS, with the same clean result on Linux.
- Remove the temporary instrumentation used to measure this branch. - Keep the before/after measurements reproducible from earlier commits. - Restore the plain Diesel connection manager.
cds-amal
marked this pull request as ready for review
August 23, 2026 01:36
Contributor
Greptile SummaryThis PR reduces database-pool resource usage by sharing one process-wide r2d2 scheduler, lazily growing SQLite pools from one connection, and applying SQLite’s busy timeout before the remaining connection pragmas.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains. Important Files Changed
Reviews (2): Last reviewed commit: "test(core): remove the storage census" | Re-trigger Greptile |
cds-amal
marked this pull request as draft
August 23, 2026 01:48
cds-amal
marked this pull request as ready for review
August 25, 2026 19:27
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Following #759, this PR addresses r2d2 defaults that cause Surfpool's connection pools to allocate resources ahead of need:
busy_timeoutbefore other connection pragmas so lazy pool growth can tolerate lock contention.Pooling behavior, connection limits, and lifetimes are unchanged.
Threads
r2d2 creates a private three-thread scheduler for every pool unless one is supplied. Pools live one per surfnet (SQLite, since #759) or one per database URL (Postgres), so the cost scales with live pools.
One process-wide scheduler now serves all pools: 3 threads per process instead of 3 per pool.
This is safe across pool lifetimes because r2d2 reap jobs hold a
Weakreference to their pool; jobs for dropped pools retire as no-ops.Connections
r2d2 defaults
min_idletomax_size, so each SQLite pool opened all ten connections at surfnet startup, before any query ran.SQLite now matches Postgres:
min_idle = 1max_size = 10SQLite Pragma order
Lazy growth exposed a connection-setup race.
busy_timeoutwas the last SQLite pragma applied during connection setup, so earlier statements ran with SQLite's default timeout of zero. If another connection held a lock, setup failed immediately and r2d2 discarded and replaced the connection.On main this is latent because connections are created before startup begins writing. With lazy growth, connection setup can interleave with those writes.
busy_timeoutnow runs first, so setup waits out contention like later traffic does.Validation
The branch includes temporary lifecycle counters and an ignored census workload; the final commit removes them.
Run the census with:
cargo test -p surfpool-core --lib storage::census -- \ --ignored --nocapture --test-threads=1For ten on-disk surfnets running zero queries:
min_idlemin_idlebusy_timeout(tip)The endpoints are deterministic across macOS and Linux. The intermediate commit varies because it exposes the setup race; moving
busy_timeoutfirst closes it on both.Dropping the ten held surfnets returns all counters to zero, preserving the connection-release behavior established by #759.
For threads, three full core-suite runs (~700 tests, Linux, 16 cores) peaked at exactly 3
r2d2-workerthreads for the process. Main pays three per live pool; ten held surfnets therefore require thirty.Historical context
Before #759, isolated in-memory pools were cached for the process lifetime. A test binary was observed at 8,316 threads against macOS's 9,216 per-process limit, with 96% named
r2d2-worker.#759 removed the cache. This PR removes the remaining per-pool resource multiplier.