Keep Omniscio resident in memory (Windows working-set floor)
A Windows-only Settings → Performance toggle that keeps Omniscio's own memory resident in physical RAM so its pages cannot be trimmed out to the pagefile, with a VirtualLock page pin as the primary mechanism, a per-process working-set floor as the fallback, and an option to serve the database from private memory.
What it is
A Windows-only Settings → Performance toggle that keeps Omniscio's own memory resident in physical RAM so its pages can't be trimmed out to the pagefile when the machine is starved. It is the memory twin of the CPU-side Boost Omniscio interface priority: where that keeps Omniscio scheduled under CPU contention, this keeps Omniscio resident under memory pressure.
The primary mechanism is the resident PIN, not the floor this page describes (updated 2026-06-28). The
keepAmcResidentInMemorytoggle is now default-ON, and its PRIMARY action is a trueVirtualLockpage-pin of the main process's DB + hot heap — needing no admin (only the working-set min raised first), because a hard working-set minimum alone is a HINT Windows trims under real pressure (measured: a 600 MB floor trimmed to 1 MB). The pin is sized from a STABLE basis (DB mapped footprint + a fixed heap allowance, NOT the trimmable live working set — a 2026-07-05 fix, after it was found unwinding from ~3.7 GB→~1.2 GB under load) so it holds through the swarm storm. SSOT: resident-lock.ts + the resident-pin contract. The working-set floor documented below is now the FALLBACK — applied only where the pin can't run (non-Windows / < 13 GB RAM / FFI unavailable). The floor details below are still accurate for that fallback; a fuller rewrite to lead with the pin is a tracked follow-up.
Escalation when the pin is DEFEATED — "Serve the database from private memory" (2026-07-14).
VirtualLockcan hold private (heap) pages but CANNOT hold a file-backed memory-map against Windows' cache-manager trim under sustained disk load — so on a swarm-busy machine the pin is repeatedly DEFEATED: the database's ~2 GB file-mapped window keeps getting evicted despite the lock, hard-faulting the main thread back off the busy disk (the whole-app STARVED freeze). The opt-in Settings → Performance → "Serve the database from private memory (Windows only)" toggle (keepDbInPrivateCache, default OFF, takes effect on the next restart) fixes this at the source: it opens the database with the file-mapped window OFF (mmap_size=0) and a large private page cache instead, so the hot database lives in committed heap the pin CAN hold. Trade-off: a cache miss falls to a synchronous read from disk — bounded, since the cache is sized to hold the whole database with headroom. Fully reversible: turn it off and restart. SSOT: the resident-pin contract (R9).
The problem it solves
When many Claude CLI sessions run at once, total committed memory climbs and Windows starts trimming working sets — evicting cold pages out to the pagefile to free physical RAM. Omniscio's own processes are fair game: if Omniscio has been in the background (you were in your IDE or browser), Windows will happily page out its renderer's heap. When you Alt-Tab back, Omniscio has to fault all those pages back in from disk — the window paints stale, scrolling stutters, the first click lags. That is not slow code; it is Omniscio's memory having been demoted to disk and now crawling back.
Omniscio already pushes the other direction on the session children — session working-set trimming actively evicts idle Claude CLI children toward the pagefile to keep headroom. This toggle is the counterpart for Omniscio itself: hold a floor of Omniscio's own pages resident so the window stays instant even when the box is under memory pressure.
Where to find it
Settings → Performance → Keep Omniscio resident in memory (Windows only). Off by default, reapplies live without a restart, hidden entirely on macOS / Linux.
How it behaves
What the toggle does
When on, Omniscio sets a hard working-set minimum on every one of its own Electron processes — main, renderer, GPU, utility, plus any helper renderer Electron spawns later — via Win32 SetProcessWorkingSetSizeEx with the QUOTA_LIMITS_HARDWS_MIN_ENABLE flag. A hard minimum is one Windows actually honors: it will not trim that process below the floor even under memory pressure. The companion QUOTA_LIMITS_HARDWS_MAX_DISABLE flag is set at the same time, so Omniscio only ever establishes a floor — it never caps its own working set.
The floor is 128 MB per process. Across Omniscio's ~5 Electron processes that reserves roughly 0.5–0.75 GB of resident headroom — enough to keep each process's hot pages (the renderer heap, the main event loop, the V8 code) in RAM without hoarding memory the rest of the system needs.
Behaviour details:
- Rides on a privilege Omniscio already holds — no admin needed. Setting a working-set minimum requires
SeIncreaseWorkingSetPrivilege, which Omniscio already enables for its existing working-set features (win32-privileges.ts). This floor is only that working-set minimum — a strong hint Windows honors, NOT an unbreakable pin. (True page-locking is the resident pin described in the note above:VirtualLock, which — contrary to a common misconception — needs no admin either, only the raised working-set min for quota; the admin-gatedSeLockMemoryPrivilegeis a different API that Omniscio does not use.) - Self-verifying (the anti-silent-no-op guard). Right after Omniscio sets its own floor, it reads the value back from Windows (
GetProcessWorkingSetSizeEx) and logs a loud[ResidentFloor]warning if the floor did not actually take. This exists because a sibling memory feature once failed a privilege check and silently did nothing in production for months — the read-back makes that failure mode loud instead of invisible. - Idempotent + 30s refresh. Flipping it on once is enough; a 30s interval re-applies the floor to Omniscio's main process (cheap) and catches any newly-spawned Electron child. The refresh only ever touches Omniscio's freshly-enumerated current processes, so it can never accidentally pin an unrelated app that reused an old process id.
- Clean turn-off. Disabling sweeps the floor off the union of every process Omniscio floored AND every Omniscio process currently alive — so a child that spawned between refresh ticks cannot be left with a lingering floor.
- Non-fatal failure mode. Any
OpenProcess/SetProcessWorkingSetSizeExfailure logs[ResidentFloor] ...and degrades to a no-op; Omniscio continues normally. - No-op on macOS / Linux.
process.platform !== 'win32'short-circuits before any kernel32 work, and the toggle is hidden in Settings on non-Windows. - Not touched by the session governors. This floors Omniscio's OWN processes; it has nothing to do with the Claude CLI children's Job Object. The CPU-Burst window (which lifts the session limiters) deliberately leaves the floor in place — keeping Omniscio resident is wanted during a burst, not suspended.
The honest trade-off
The reserved RAM is RAM the background sessions cannot use. Under genuine memory exhaustion that is an intentional choice — favour a responsive Omniscio window over a little extra memory for background turns — which is exactly why it is opt-in and off by default. It keeps a floor resident; it does not lock the whole app in RAM, and Windows can still page beyond the floor. If you run 1–3 sessions you will never see the symptom it fixes; it is discoverable for the user who reports "Omniscio feels sluggish when I come back to it after a heavy run."
Why these specific defaults
- Off by default. Situational — it trades a slice of RAM for window responsiveness under pressure, which most users do not need.
- 128 MB per process. Big enough to keep each Electron process's hot pages resident, small enough that ×5 processes stays well under ~1 GB. A tunable constant, not a user-facing knob.
- A hard floor, not a soft one. A soft
SetProcessWorkingSetSizeminimum is only an advisory hint Windows ignores under real pressure — a placebo for this feature's whole purpose. The hard-minimum flag is the version Windows actually honors, and it still needs no admin rights.
For agents
How this is verified
- Pure-helper unit tests: tests/unit/process/resident-floor.test.ts — 22 tests covering the hard-min / max-disable flag table, the floor-size bounds math, the read-back "is it honored" predicate (including the historical silent-no-op case where the min flag is absent), the recycled-pid reconcile under churn, and the disable live-sweep union. The Win32 FFI path is left unmocked by design (it cannot be exercised without a real Windows kernel; see the contract).
- Runtime self-check: the read-back-and-warn described above is the field guard — a green unit run proves the logic, the self-check proves the OS actually honoured it on the user's machine.
- Manual smoke (Windows): enable the toggle, open Task Manager → Details → add the "Working set (memory)" column, and confirm Omniscio's processes hold at or above the floor while the box is under memory pressure from many sessions.
Implementation pointers
- src/main/process/resident-floor.ts —
applyAmcResidentFloor(settings). Win32SetProcessWorkingSetSizeEx(hard-min | max-disable) on self + every Electron child viaapp.getAppMetrics(), with aGetProcessWorkingSetSizeExread-back. 30s refresh catches new children; disable sweeps tracked ∪ live. Cross-platform shim no-ops off Windows. - src/main/process/win32-privileges.ts — enables
SeIncreaseWorkingSetPrivilege(shared with the existing working-set features). - src/main/index.ts — applies the floor at startup, right beside the priority-boost call.
- src/main/services/settings-apply.ts — re-applies it live when the
keepAmcResidentInMemorysetting changes. - src/renderer/src/features/settings/PerformanceSettings-definitions.tsx — the
keep-amc-resident-in-memorytoggle definition, listed inWINDOWS_ONLY_PERFORMANCE_IDSso it hides on macOS / Linux. - Behavior contract: resident-floor-contract.md.
Related
- Boost Omniscio interface priority + adaptive E-core delegation — the CPU-side siblings. Those keep Omniscio scheduled under CPU contention; this keeps Omniscio resident under memory pressure. Same Settings → Performance section, same Omniscio-self / Windows-only / off-by-default pattern.
- Session memory paging (working-set trimming) — the counterpart that pushes the session children's idle pages out to the pagefile to free RAM. This toggle holds Omniscio's own pages in; that one pushes the children's out.
- Session CPU cap — the session-side CPU limiter that started this family of performance controls.
Last verified 2026-09-23