pi-lens
Version:
Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo
125 lines (112 loc) • 8.34 kB
Markdown
# LSP idle-eviction measurement
Per-server cost and safety of releasing an idle language-server client, measured
by the nightly so each server's `idleEviction` declaration in
`clients/lsp/server.ts` can be made from evidence (#3645). Generated by
`node scripts/measure-lsp-idle-eviction.mjs [--install]` (requires
`npm run build:dist`); it changes no server's policy.
For each registry server the probe spawns the server on its smoke fixture,
records the first diagnostics, then makes the server evictable in the probe
process only and lets the real idle-eviction timer release it. The next request
respawns it through the ordinary path. A server is `eligible` only when the
respawned server reports every finding it reported before eviction; the
`coverage` column is that comparison, and for an auxiliary scanner it is the
content-bound coverage check the auxiliary freeze depends on. A server that
cannot demonstrate it is never proposed for eviction on perf grounds alone.
_Last generated: 2026-10-07 on linux; 48 registry servers: 32 eligible, 0 vetoed, 2 inconclusive, 14 unavailable (0 not reached: budget)._
## Per-server rows
Only stable columns are committed, so the nightly refresh changes this file
only when a server's outcome changes. The measured init duration, resident
memory of the server's process tree and post-eviction cold start are in the
nightly run's step log and job summary, one row per server. `n/a` means not
measured, never zero: **respawn** is whether the next request after eviction
brought the server back, **coverage** is whether the respawned server kept
every baseline finding.
A server that reports extra findings after the respawn (`widened`) still reads
`preserved`, because nothing was lost, but a first scan that grows on respawn
is a sign the baseline was partial. Any policy flip needs `preserved` on
several nights, not one; a `widened` disclosure is per run and is shown in the
step log only, because it flaps.
| server | role | declared | result | reason | respawn | coverage |
|---|---|---|---|---|---|---|
| ast-grep | auxiliary | unmeasured | eligible | · | ok | preserved |
| bash | primary | transparent | eligible | · | ok | preserved |
| clojure | primary | transparent | eligible | · | ok | preserved |
| cmake | primary | unmeasured | inconclusive | no-baseline | n/a | unproven |
| cpp | primary | transparent | eligible | · | ok | preserved |
| csharp | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
| css | primary | transparent | eligible | · | ok | preserved |
| cue | primary | unmeasured | eligible | · | ok | preserved |
| dart | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
| deno | primary | transparent | eligible | · | ok | preserved |
| docker | primary | unmeasured | eligible | · | ok | preserved |
| docker-official | primary | unmeasured | unavailable | no-fixture | n/a | n/a |
| elixir | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
| expert | primary | unmeasured | eligible | · | ok | preserved |
| fish | primary | transparent | eligible | · | ok | preserved |
| fsharp | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
| gleam | primary | unmeasured | eligible | · | ok | preserved |
| go | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
| haskell | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
| html | primary | transparent | eligible | · | ok | preserved |
| java | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
| json | primary | unmeasured | eligible | · | ok | preserved |
| kotlin | primary | unmeasured | eligible | · | ok | preserved |
| lua | primary | unmeasured | eligible | · | ok | preserved |
| marksman | primary | transparent | eligible | · | ok | preserved |
| nix | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
| ocaml | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
| omnisharp | primary | unmeasured | unavailable | no-fixture | n/a | n/a |
| opengrep | auxiliary | transparent | eligible | · | ok | preserved |
| php | primary | transparent | eligible | · | ok | preserved |
| powershell | primary | unmeasured | eligible | · | ok | preserved |
| prisma | primary | transparent | eligible | · | ok | preserved |
| python | primary | transparent | eligible | · | ok | preserved |
| python-jedi | primary | unmeasured | eligible | · | ok | preserved |
| ruby | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
| rust | primary | unmeasured | eligible | · | ok | preserved |
| shuck | primary | unmeasured | unavailable | server-not-started | n/a | n/a |
| svelte | primary | unmeasured | eligible | · | ok | preserved |
| swift | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
| terraform | primary | unmeasured | eligible | · | ok | preserved |
| tinymist | primary | unmeasured | eligible | · | ok | preserved |
| toml | primary | unmeasured | eligible | · | ok | preserved |
| typescript | primary | transparent | eligible | · | ok | preserved |
| typos | auxiliary | unmeasured | eligible | · | ok | preserved |
| vue | primary | unmeasured | inconclusive | no-baseline | n/a | unproven |
| yaml | primary | transparent | eligible | · | ok | preserved |
| zig | primary | unmeasured | eligible | · | ok | preserved |
| zizmor | auxiliary | unmeasured | eligible | · | ok | preserved |
## Declared versus measured
`drift` means the registry evicts a server the measurement vetoes. A `proposal`
or `info` line is for a maintainer to act on in a follow-up; this run changed
nothing.
- **ast-grep** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **cue** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **docker** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **expert** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **gleam** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **json** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **kotlin** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **lua** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **powershell** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **python-jedi** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **rust** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **svelte** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **terraform** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **tinymist** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **toml** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **typos** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **zig** [proposal] declared unmeasured but eviction and respawn preserved its findings
- **zizmor** [proposal] declared unmeasured but eviction and respawn preserved its findings
## Reasons
- `no-fixture`: No smoke fixture routes to this server, so there is nothing to spawn.
- `tool-unavailable`: A tool this server's fixture needs could not be installed or found on the generating host.
- `setup-failed`: The fixture's workspace setup step failed.
- `server-not-started`: The fixture ran but this server never became a live client.
- `budget-exhausted`: The run's wall-clock budget ended before this server was reached.
- `probe-error`: The probe itself threw before it had a baseline.
- `no-baseline`: The server produced no finding on the fixture, so nothing can show its coverage survives eviction.
- `not-evicted`: The idle-eviction timer did not release the client within the bound.
- `client-died`: The client went away without an idle-eviction record, so the release was a crash, not the eviction path.
- `respawn-failed`: After eviction the next request could not bring the server back.
- `findings-narrowed`: After the respawn the server reported fewer findings than before eviction.