Skip to content

perf(workspace): drop the pools and snapshots of unused databases - #945

Open
psteinroe wants to merge 5 commits into
fix/nested-config-pathsfrom
perf/drop-unused-connections
Open

psteinroe wants to merge 5 commits into
fix/nested-config-pathsfrom
perf/drop-unused-connections

Conversation

@psteinroe

Copy link
Copy Markdown
Collaborator

Stacked on #936 → #921 → … → #881. Must merge after #881.

With nested configurations every database a configuration points at gets a connection pool and a schema snapshot, and nothing ever dropped them. Editing a nested config to point at another database, renaming a folder, or removing a workspace folder left the old pool (with its open connections) and its snapshot in memory until the server stopped. The existing idle cleanup of pools only ran when a new pool was created, and a cache hit didn't count as a use, so a pool in constant use could be evicted while an idle one stayed.

How big is a snapshot

crates/pgls_workspace/tests/snapshot_memory.rs (ignored, needs the test DB) counts the bytes a loaded Snapshot keeps allocated, with a counting global allocator:

Database Tables Columns Functions Types Snapshot
local postgres (mostly the system catalog) 212 2,020 3,285 619 2.8 MiB
+ 500 tables × 10 columns, 200 functions, 50 views, 20 enums 758 8,055 3,444 1,751 4.7 MiB

So each database costs about 3 MiB before it has any user objects, plus a few KiB per table. That's fine for a handful of databases, but it adds up when stale ones are never dropped.

Caches and their bounds

Cache Key Grows with Dropped when
ConnectionManager.pools host, port, user, database distinct databases in use new: no project's root or nested settings use it (after update_settings, update_nested_settings, unregister_project_folder); unused for 5 min (fixed: hits count, the check runs at most once a minute on any use); settings fingerprint changes
connections inside a pool — concurrent queries new: sqlx closes a connection idle for 5 min (idle_timeout, was sqlx's 10 min default)
ConnectionManager.failures same failing databases success, settings change, new: unused
SnapshotManager.db_schemas same distinct databases loaded, ~3–5 MiB each new: unused (as above); new: not used for 30 min, loaded again on the next use; invalidate_schema_cache
catalog_base, snapshot_before — one entry each replaced on the next use (unchanged)
session root_files, configuration_files, real_folders workspace folder folders rebuilt on every reload

Evictions are logged at debug level; a dropped pool or snapshot is created again on the next use, so results don't change.

LastUsed (an atomic timestamp) lets a cache hit under the read lock record a use.

Tests

  • connection_manager: unused_connections_are_dropped, idle_pools_are_closed (incl. the once-a-minute check).
  • snapshot_manager: unused_snapshots_are_dropped, idle_snapshots_are_dropped.
  • pgls_workspace: the_connection_of_a_removed_configuration_is_dropped, against the test DB. A nested config that connects keeps one pool and one snapshot; moving it to another folder with the same database keeps them; removing it drops both.

Not covered

After a configuration changes or a project is removed, drop the pools,
failures and schema snapshots of the connections no settings use any
more. Close pools idle for five minutes (cache hits now count as a use),
let sqlx close idle connections after the same time, and drop snapshots
unused for 30 minutes. Add a test that measures snapshot sizes.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant