Files
wehub-resource-sync a789495a98
FreeBSD Smoke / FreeBSD Smoke (x86_64) (push) Has been cancelled
CI / Quality Guardrails (push) Has been cancelled
CI / Build & Test (macos-latest) (push) Has been cancelled
CI / Build & Test (ubuntu-latest) (push) Has been cancelled
CI / Build & Test (windows-latest) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / PowerShell Syntax (push) Has been cancelled
CI / Windows Cross-Target Check (Linux) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:34 +08:00

151 lines
4.9 KiB
Markdown

# Memory Regression Budget
Status: active guardrail
Updated: 2026-04-18
This document defines the current memory regression budget for jcode.
The goal is not to freeze memory usage forever. The goal is to make memory changes:
- measurable
- reviewable
- intentionally justified
Where possible, budgets below are tied to counters and caps already exposed by the codebase rather than guessed RSS numbers.
## How to collect the metrics
Use existing debug surfaces instead of ad hoc instrumentation:
- TUI aggregate memory profile: `:debug memory`
- TUI memory sample history: `:debug memory-history`
- Markdown cache profile: `:debug markdown:memory`
- Mermaid cache profile: `:debug mermaid:memory`
- Agent/session memory profile via debug socket: `agent:memory`
Primary sources in code:
- `src/tui/app/debug_cmds.rs`
- `src/tui/memory_profile.rs`
- `src/session.rs`
- `src/tui/markdown.rs`
- `src/tui/mermaid.rs`
- `src/runtime_memory_log.rs`
## Budget model
We use two kinds of budgets:
1. Hard caps
- These are explicit limits already enforced by caches.
- Regressions here mean the code changed its bound or bypassed it.
2. Ratchet expectations
- These are expected relationships between memory counters.
- Regressions here are allowed only with explanation and updated docs/tests.
## Hard caps
### Markdown cache budget
Source: `src/tui/markdown.rs`
| Metric | Budget | Why |
|---|---:|---|
| `highlight_cache_entries` | `<= 256` | Explicit cache cap (`HIGHLIGHT_CACHE_LIMIT`) |
Required review action if violated:
- explain why the cache limit changed
- update this doc
- update any affected tests or benchmarks
### Mermaid cache budget
Sources:
- `src/tui/mermaid.rs`
- `src/tui/mermaid_cache_render.rs`
| Metric | Budget | Why |
|---|---:|---|
| `render_cache_entries` | `<= 64` | Explicit render-cache cap (`RENDER_CACHE_MAX`) |
| `image_state_entries` | `<= 12` | Explicit protocol-state cap (`IMAGE_STATE_MAX`) |
| `source_cache_entries` | `<= 8` | Explicit decoded-source cap (`SOURCE_CACHE_MAX`) |
| `active_diagrams` | `<= 128` | Explicit active-diagram cap (`ACTIVE_DIAGRAMS_MAX`) |
| `cache_disk_png_bytes` | `<= 50 MiB` | Explicit on-disk cache cap (`CACHE_MAX_SIZE_BYTES`) |
| `cache_disk_max_age_secs` | `<= 259200` | 3-day expiry (`CACHE_MAX_AGE_SECS`) |
Required review action if violated:
- document the new limit and reason
- verify eviction still works
- verify no unbounded growth path was introduced
## Ratchet expectations
### Session and transcript memory
Source: `src/session.rs`, `src/tui/memory_profile.rs`
These are not strict caps yet, but they are expected relationships.
| Metric relationship | Expectation |
|---|---|
| `provider_messages_cache.count` vs `messages.count` | Should remain in the same order of magnitude for a single session, and normally track the transcript closely |
| `session_provider_cache_json_bytes` vs `canonical_transcript_json_bytes` | Should remain comparable for normal chat flows, not explode independently |
| `transient_provider_materialization_json_bytes` | Should return to zero or near-zero outside active materialization-heavy paths |
| `display_large_tool_output_bytes` | Large values require explanation because they usually mean raw tool output is being retained too aggressively in the UI |
Required review action if violated:
- show before/after memory profiles
- explain which retention path grew
- prefer fixing duplication before raising any budget
### Runtime memory log expectations
Source: `src/runtime_memory_log.rs`
Runtime memory logs are the regression detection mechanism, not just a debug feature.
Expected behavior:
- server/client logs should be sufficient to explain large changes in:
- session/transcript totals
- provider cache totals
- TUI display totals
- side panel totals
- new large memory owners should emit attributable signals instead of appearing only as unexplained RSS growth
Required review action if violated:
- add or improve attribution before accepting the memory increase
## Review checklist for memory-affecting changes
When changing memory-heavy code, capture and include:
1. Which counters changed?
- aggregate `:debug memory`
- targeted `:debug markdown:memory` / `:debug mermaid:memory`
- `agent:memory` when session/provider cache behavior changes
2. Was a hard cap changed?
- if yes, explain why the old cap was insufficient
3. Did duplication increase?
- canonical transcript
- provider cache
- materialized provider view
- display copy
- side-panel copy
4. Did observability remain adequate?
- if memory grew, can logs/profiles explain where?
## Current initial budget summary
These are the concrete enforced limits today:
- Markdown highlight cache entries: 256
- Mermaid render cache entries: 64
- Mermaid protocol image-state entries: 12
- Mermaid decoded source-cache entries: 8
- Mermaid active diagrams: 128
- Mermaid on-disk PNG cache: 50 MiB, max age 3 days
Any intentional change to those limits must update this document in the same PR.