Browse documentation

Technical documentation / Reference

Memory Usage Profiling Workflow

Maintainer workflow for credential-free peak RSS checks. Default path is offline: scripts/profile_memory.py runs the same ignored Rust profiling harness tests as CPU profiling with a temporary synthetic MC_HOME, no auth.json, credential-looking environment variables removed from child processes, local fixtures, and no live provider/network command.

Requirements

Default credential-free run

python3 scripts/profile_memory.py --repo . --all --iterations 1

Artifacts:

target/profiling/memory/profile-results.json
target/profiling/memory/profile-summary.md
target/profiling/memory/<scenario>.log

Run one scenario and print machine-readable JSON:

python3 scripts/profile_memory.py --repo . --scenario provider_sse_parser --iterations 1 --json

Self-test:

python3 scripts/profile_memory.py --self-test

Scenarios

Memory scenarios reuse CPU harness workloads; only the measurement wrapper changes. The Rust test names stay profile_cpu_* because they are shared synthetic workloads.

scenarioharnessexercises
startup_discoveryprofile_cpu_startup_discoverylocal settings, instruction, skill, session, and model-cache discovery
provider_sse_parserprofile_cpu_sse_parserResponses and Chat Completions SSE parser fixtures
rendering_heavy_transcriptprofile_cpu_rendering_heavy_transcripttranscript rendering, markdown, code highlighting, diff/plain projection
tui_streaming_simulationprofile_cpu_tui_streaming_simulationassistant deltas, activity events, transcript/activity caches
tool_timeout_cleanupprofile_cpu_tool_timeout_cleanupUnix process-group timeout cleanup path

Metrics

profile_memory.py warms the release test build first with cargo test --release --no-run, then runs each selected scenario in an isolated helper process. The helper reads resource.getrusage(RUSAGE_CHILDREN).ru_maxrss after the scenario command exits.

JSON fields:

Unit normalization: Darwin reports ru_maxrss in bytes; Linux reports KiB. The script normalizes both to bytes.

Comparison method

  1. Compare only runs with the same machine, OS, Rust version/profile, and allocator, under similar system load.
  2. Run:
python3 scripts/profile_memory.py --repo . --all --iterations 1
  1. Save measured rows from target/profiling/memory/profile-results.json with the run timestamp, commit, platform, Rust version and profile in your comparison record. Preserve earlier measurements; mark missing values unknown rather than inferring them. Keep raw artifacts out of Git.
  2. Investigate a >5% peak RSS increase versus the previous comparable run; it is not a CI gate.
  3. Use profile-summary.md for quick review and scenario logs for harness output.

Memory numbers are not comparable across OSes, allocators, Rust versions, debug/release profiles, or machines.

Optional deeper inspection

The default workflow above is credential-free and offline. Live-provider memory checks are outside that workflow and involve secrets: run them only when credentials and network are intentionally available, and never store secret strings, account identifiers, auth flow codes, or credential payloads in fixtures or artifacts.

Optional local tools when installed:

# macOS
/usr/bin/time -l cargo test --release profile_cpu_rendering_heavy_transcript -- --ignored --nocapture
leaks <pid>
# Instruments Allocations can inspect a manually launched process.

# Linux
/usr/bin/time -v cargo test --release profile_cpu_rendering_heavy_transcript -- --ignored --nocapture
heaptrack cargo test --release profile_cpu_rendering_heavy_transcript -- --ignored --nocapture
valgrind --tool=massif cargo test --release profile_cpu_rendering_heavy_transcript -- --ignored --nocapture

Optional tool output belongs under target/profiling/memory/ or another ignored local path.

Edit this page on GitHub ↗