Browse documentation

Technical documentation / Reference

CPU Hotspot Profiling Workflow

Maintainer workflow for issue #48 / PRD-0056. Default path is credential-free and offline: scripts/profile_cpu.py runs ignored Rust harness tests with a temporary synthetic MC_HOME, no auth.json, credential-looking environment variables removed from child processes, local SSE fixtures, local session/cache/skill data, and no live model-catalog refresh.

Requirements

Default credential-free run

python3 scripts/profile_cpu.py --repo . --all --min-seconds 3

Automatic wrapper artifacts:

target/profiling/issue-48/profile-results.json
target/profiling/issue-48/profile-summary.md
target/profiling/issue-48/<scenario>.log
target/profiling/issue-48/tui-render-pipeline.json

The wrapper does not collect .sample.txt files or idle PTY samples. Collect those separately using the manual macOS sampling workflow.

Run one scenario:

python3 scripts/profile_cpu.py --repo . --scenario provider_sse_parser --min-seconds 10
cargo test --release profile_cpu_sse_parser -- --ignored --nocapture

Self-test:

python3 scripts/profile_cpu.py --self-test

Mission Control render pipeline

Default render profiling is credential-free and uses Ratatui TestBackend; it does not enter raw mode, alternate screen, provider transport, network, or real stdout ANSI output. Historical baseline results live in 1.

Run full harness through Python wrapper:

python3 scripts/profile_cpu.py --repo . --scenario tui_render_pipeline --min-seconds 5

Run all render-pipeline scenarios once through the exact aggregate test (a partial filter also selects six individual tests):

cargo test --release --lib test_support::profile_harness::profile_tui_render_pipeline -- --exact --ignored --nocapture

Run one scenario directly:

cargo test --release profile_tui_render_pipeline_idle -- --ignored --nocapture
cargo test --release profile_tui_render_pipeline_streaming -- --ignored --nocapture
cargo test --release profile_tui_render_pipeline_heavy_transcript -- --ignored --nocapture
cargo test --release profile_tui_render_pipeline_scroll -- --ignored --nocapture
cargo test --release profile_tui_render_pipeline_resize -- --ignored --nocapture
cargo test --release profile_tui_render_pipeline_modal -- --ignored --nocapture

Direct Cargo runs print results to stdout; they do not write a JSON artifact. The Python wrapper writes:

target/profiling/issue-48/tui-render-pipeline.json

Backend modes are selected by PROFILE_TUI_RENDER_BACKEND:

PROFILE_TUI_RENDER_BACKEND=test cargo test --release --lib test_support::profile_harness::profile_tui_render_pipeline -- --exact --ignored --nocapture
PROFILE_TUI_RENDER_BACKEND=crossterm-sink cargo test --release --lib test_support::profile_harness::profile_tui_render_pipeline -- --exact --ignored --nocapture
PROFILE_TUI_RENDER_BACKEND=crossterm-real cargo test --release --lib test_support::profile_harness::profile_tui_render_pipeline -- --exact --ignored --nocapture
backend modepurposecaveat
testdefault Ratatui TestBackend; measures process-side render and diff costrecords 0 for stdout/write/flush; no terminal emulator paint
crossterm-sinkmeasures generated ANSI bytes and crossterm write/flush work against an in-memory sinkstill does not measure terminal emulator paint
crossterm-realwrites to real stdout for manual terminal-path checksenv-gated; use only in disposable terminal; manual real-TTY validation has not been recorded in baseline

Metrics:

metricmeaninginterpretation
terminal_draw_msend-to-end Terminal::draw wall time in default TestBackend modeclosest process-side total draw number for baseline tables
controlled_draw_msphase-instrumented manual frame path wall timeuse when comparing render_draw_ms, diff_ms, backend draw, write, and flush phases
render_draw_msMission Control render::draw CPU timehistorical baseline bottleneck: 71-82% of p50 frame time; rerun to assess current cost
diff_msRatatui buffer diff durationnot the historical baseline bottleneck: 0.049-0.111 ms
diff_cellschanged-cell count emitted by Ratatui diffhigh values can raise terminal output, but baseline resize still diffed 7995 cells in 0.111 ms p50
changed_cell_ratiochanged cells divided by terminal arearesize/modal first frames should be high; steady idle should be near zero
backend_draw_msbackend draw call duration inside controlled pathzero/near-zero for TestBackend; useful for crossterm modes
stdout_bytesANSI/output bytes generated by crossterm backendzero for TestBackend; terminal I/O ceiling needs crossterm modes
write_calls / write_mswriter call count and write durationzero for TestBackend; sink/real backends isolate output overhead
flush_calls / flush_msflush count and flush durationprocess flush time is not terminal emulator paint telemetry
frames_per_secscripted harness throughputnot display refresh rate; compare same machine/profile/backend/area only

Interpretation rules:

  1. Compare same backend, terminal area, Rust profile, scenario mix, and machine.
  2. If render_draw_ms dominates p50 frame time, optimize Mission Control render/state projection first.
  3. If diff_ms stays sub-millisecond while diff_cells is high, Ratatui diff is not blocking frame throughput.
  4. If stdout_bytes, write_ms, or flush_ms rise in crossterm modes, terminal I/O may cap real-world FPS even when TestBackend is fast.
  5. Treat TestBackend results as process-side render ceiling only. Real-world ceiling depends on terminal emulator write/flush/paint behavior.

Large-response and text-modal comparisons

These ignored, credential-free workflows compare current render paths with local reference algorithms, not historical binaries or terminal-emulator paint:

cargo test --release --locked --lib streaming_viewport_large_response_workload -- --ignored --nocapture
cargo test --release --locked --lib text_modal_large_document_workload -- --ignored --nocapture

Streaming uses independent states with identical synthetic events and alternates measurement order. It reports initial indexing separately, then medians across 30 appends. rebuild disables only completed-prefix reuse; full_reference materializes and measures every line. Text-modal results include Terminal::draw with TestBackend, across 21 top/middle/end draws.

Representative local results on macOS with Rust 1.98.1, release profile, September 2026:

Synthetic workloadViewport medianSparse rebuild medianFull-reference median
390,000-byte multiline ASCII, 80×240.89 ms8.00 ms36.53 ms
430,000-byte multiline Unicode, 80×241.30 ms45.57 ms38.33 ms
276,000-byte unbroken Unicode, 80×249.96 ms9.96 ms10.08 ms
Large system-prompt text, 120×405.66 ms16.29 ms

The multiline Unicode cold index took 45.52 ms versus 38.24 ms for full formatting. Completed-prefix reuse—not faster cold Unicode wrapping—produces the steady append improvement. Reuse requires exact equality of the fully sanitized completed prefix and compatible row/layout identity. Unbroken responses retain full formatting because sparse rebuilding measured slower. Whole-source sanitization, cold indexing, final Markdown, explicit copying, and modal height/prefix scans remain full-work paths. Allocations and physical-terminal latency were not measured.

Scenarios

scenarioharnessexercises
startup_discoveryprofile_cpu_startup_discoverysrc/config, src/instructions, src/skills, src/sessions, src/model_catalog local cache reads
provider_sse_parserprofile_cpu_sse_parsersrc/providers/stream/mod.rs::StreamParser using Responses and Chat Completions SSE fixtures
rendering_heavy_transcriptprofile_cpu_rendering_heavy_transcriptsrc/tui/state, src/tui/render/transcript.rs, src/rendering/markup.rs, src/rendering/highlight.rs
tui_render_pipelineprofile_tui_render_pipelinefull Mission Control Terminal::draw, controlled render::draw, Ratatui diff, TestBackend/crossterm byte and flush accounting
tui_streaming_simulationprofile_cpu_tui_streaming_simulationassistant deltas, activity events, transcript/activity caches
tool_timeout_cleanupprofile_cpu_tool_timeout_cleanupsrc/tools/process.rs::terminate_child_tree_and_wait process-group cleanup
idle Mission Control TUImanual real terminal or non-interactive PTYstatic --no-session wakeups/CPU while no prompt is submitted

Issue #381 skill discovery benchmark

The dedicated release benchmark uses 55 selected skills plus three deterministic diagnostics across small, empty-body, representative-body, near-1-MiB, disabled, malformed, colliding, and oversized fixtures. The fixture contains 5,439,395 aggregate body bytes. That count describes generated fixture content; bytes read and allocations were not instrumented and are not claimed.

Both runs used PROFILE_CPU_ITERATIONS=25 cargo test --release profile_cpu_discover_skills -- --ignored --nocapture on a MacBook Pro Mac17,8 with Apple M5 Pro, 64 GB RAM, macOS 27.0 arm64, and rustc 1.98.0, release profile.

runexact commitelapsed / iterationsfirst read skill://near-0saved artifact
metadata-body baseline4085f5f4ed51f0b219b7ca03e4e86ae97baea283325 ms / 25687 µstarget/profiling/issue-381/before.log
metadata-only discovery40d6f1410c6097e12b352afd88bb34d87402165c74 ms / 25723 µstarget/profiling/issue-381/after-final.log

The dedicated result improved from 13.0 ms to 3.0 ms per iteration (about 77%). This is a same-machine synthetic comparison, not evidence of a user-visible startup regression or a hard budget. As secondary context only, the aggregate startup_discovery harness completed 25 iterations in 42 ms at the optimized commit (target/profiling/issue-381/startup-after.log); it also measures settings, instructions, sessions, and model-cache work, and the committed Issue #48 profile identifies session listing as dominant and skill discovery as secondary.

macOS sampling

Harness sample:

PROFILE_CPU_MIN_SECONDS=20 PROFILE_CPU_ITERATIONS=1 \
  cargo test --release profile_cpu_rendering_heavy_transcript -- --ignored --nocapture &
cargo_pid=$!
sleep 1
pgrep -P "$cargo_pid" -fl magi_code
test_pid=<pid-from-pgrep>
sample "$test_pid" 10 -mayDie -file target/profiling/issue-48/rendering-heavy-transcript.sample.txt
wait "$cargo_pid"

Idle Mission Control TUI real-terminal command:

MC_HOME="$(mktemp -d)" cargo run --bin magi-code -- --no-session
# In another terminal:
pgrep -fl "magi-code.*--no-session"
sample <pid> 30 -file target/profiling/issue-48/idle-tui.sample.txt
spindump <pid> 10 -file target/profiling/issue-48/idle-tui.spindump.txt

Idle rules: do not submit a prompt, do not run /login, do not configure provider credentials, do not refresh model catalogs, exit with /quit after sampling. A non-interactive /usr/bin/script PTY baseline is acceptable for issue #48 if it launches magi-code --no-session, keeps stdin open, uses isolated MC_HOME, captures sample, and is labeled as PTY rather than physical terminal evidence. Recorded baselines below retain the launch flags used at the time.

Linux perf parity

The Linux commands provide an equivalent workflow; they have not been run unless a Linux host is named in the baseline notes:

PROFILE_CPU_MIN_SECONDS=20 PROFILE_CPU_ITERATIONS=1 \
  perf record -F 99 -g -- cargo test --release profile_cpu_tui_streaming_simulation -- --ignored --nocapture
perf report --stdio > target/profiling/issue-48/tui-streaming.perf-report.txt
perf script > target/profiling/issue-48/tui-streaming.perf-script.txt

Optional FlameGraph:

perf script | stackcollapse-perf.pl > target/profiling/issue-48/tui-streaming.folded
flamegraph.pl target/profiling/issue-48/tui-streaming.folded > target/profiling/issue-48/tui-streaming.svg

Issue #48 historical baseline

Machine baseline from target/profiling/issue-48/profile-results.json generated on 2026-05-31T07:32:23Z. macOS stack samples were collected with /usr/bin/sample for all synthetic harness scenarios plus idle TUI under a non-interactive /usr/bin/script PTY. The Linux profiler was not run on this Darwin host.

scenariodate/timemachine/OS/archRust version/profilecommandduration/iterationsprimary metricresultartifact pathnotes
startup_discovery2026-05-31T07:32:23ZDarwin 25.5.0 arm64rustc 1.95.0 releasecargo test --release profile_cpu_startup_discovery -- --ignored --nocapture3000 ms / 4401discovered_items563618466target/profiling/issue-48/startup_discovery.log; target/profiling/issue-48/startup_discovery.sample.txtsynthetic settings, sessions, skills, model cache
provider_sse_parser2026-05-31T07:32:23ZDarwin 25.5.0 arm64rustc 1.95.0 releasecargo test --release profile_cpu_sse_parser -- --ignored --nocapture3000 ms / 102104events_parsed1735768target/profiling/issue-48/provider_sse_parser.log; target/profiling/issue-48/provider_sse_parser.sample.txtlocal Responses + Chat Completions fixtures
rendering_heavy_transcript2026-05-31T07:32:23ZDarwin 25.5.0 arm64rustc 1.95.0 releasecargo test --release profile_cpu_rendering_heavy_transcript -- --ignored --nocapture3001 ms / 263rendered_units956268target/profiling/issue-48/rendering_heavy_transcript.log; target/profiling/issue-48/rendering_heavy_transcript.sample.txtmarkdown/code/diff transcript fixture
tui_streaming_simulation2026-05-31T07:32:23ZDarwin 25.5.0 arm64rustc 1.95.0 releasecargo test --release profile_cpu_tui_streaming_simulation -- --ignored --nocapture3000 ms / 1059state_units277458target/profiling/issue-48/tui_streaming_simulation.log; target/profiling/issue-48/tui_streaming_simulation.sample.txtsynthetic assistant deltas and activity deltas
tool_timeout_cleanup2026-05-31T07:32:23ZDarwin 25.5.0 arm64rustc 1.95.0 releasecargo test --release profile_cpu_tool_timeout_cleanup -- --ignored --nocapture3020 ms / 127cleanup_units254target/profiling/issue-48/tool_timeout_cleanup.log; target/profiling/issue-48/tool_timeout_cleanup.sample.txtUnix process-group termination path
idle Mission Control TUI2026-05-31T07:24:36ZDarwin 25.5.0 arm64release binary/usr/bin/script -q target/profiling/issue-48/idle-tui-pty.script.txt target/release/magi-code --tui --no-session + /usr/bin/sample <pid> 8 -mayDie8 s sample / PTY idleps CPU + stack sample0.4% CPU before sample, 0.1% CPU after sample; 6832/6853 samples in keventtarget/profiling/issue-48/idle-tui-pty-summary.json; target/profiling/issue-48/idle-tui-pty.sample.txtisolated temp MC_HOME; no prompt submitted; no provider request; no auth.json created; PTY baseline, not physical terminal

Hotspot report

Historical findings from the Issue #48 baseline above. Source paths, symbols, and priorities reflect that run, not a current bottleneck assessment.

scenariosource filefunction/symbolmetric typemetric valueprofiler artifactimpactconfidencefollow-up priority
idle Mission Control TUIsrc/tui/mod.rs + crossterm event pathMissionControlApp::run / crossterm::event::poll / keventmacOS sample stack + ps CPU6832/6853 samples blocked in kevent; 0.4% -> 0.1% CPU around 8 s sampletarget/profiling/issue-48/idle-tui-pty.sample.txt; target/profiling/issue-48/idle-tui-pty-summary.jsonidle loop appears mostly blocked on terminal events under PTY; low idle CPU on this machineHigh for PTY evidence; physical-terminal wakeups still optional confirmationP2
rendering_heavy_transcriptsrc/tui/render/transcript.rscached_transcript_lines / append_transcript_entry_linesmacOS sample stack3225 samples in MissionControlState::cached_transcript_lines; 3191 in cached_transcript_lines; 3163 in append_transcript_entry_linestarget/profiling/issue-48/rendering_heavy_transcript.sample.txtheavy transcript redraw cost; markdown projection repeated across many assistant turnsHigh; stack sample plus harness throughputP1
rendering_heavy_transcriptsrc/rendering/markup.rs + src/rendering/highlight.rsrender_markdown / highlight_codemacOS sample stack3055 samples in render_markdown; 2391 samples in highlight_codetarget/profiling/issue-48/rendering_heavy_transcript.sample.txtcode fence highlighting and Markdown parsing dominate long transcript renderingHighP1
tui_streaming_simulationsrc/tui/state/mod.rsapply_activity_event / cached_visible_nodes / collect_visiblemacOS sample stack1164 samples in apply_activity_event; 1137 in cached_visible_nodes; 447 in collect_visibletarget/profiling/issue-48/tui_streaming_simulation.sample.txtmany small activity deltas clone and rebuild visible activity stateHighP1
provider_sse_parsersrc/providers/stream.rsStreamParser::push_chunk_outcome / serde_json::de::from_traitmacOS sample stack376 samples in push_chunk_outcome; 369 in serde JSON parse beneath ittarget/profiling/issue-48/provider_sse_parser.sample.txtparser overhead is real but smaller than rendering/state hotspots in synthetic runHighP2
startup_discoverysrc/sessions/mod.rs + src/skills/mod.rsSessionManager::list / discover_skills / discover_agentsmacOS sample stack5750 samples in SessionManager::list; 303 + 301 in discover_skills; 83 + 79 in discover_agentstarget/profiling/issue-48/startup_discovery.sample.txtstartup scales with local session count first, then skill/instruction discoveryHighP2
tool_timeout_cleanupsrc/tools/process.rsterminate_child_tree_and_wait / poll_process_group_exit / signal_process_groupmacOS sample stack4525 samples in terminate_child_tree_and_wait; 3772 in poll_process_group_exit; 693 in signal_process_grouptarget/profiling/issue-48/tool_timeout_cleanup.sample.txttimeout cleanup cost dominated by sleep/process polling and subprocess probesHighP3

Historical CPU-reduction priority order

  1. P1: reduce repeated transcript markdown/render projection in heavy transcript and streaming paths. Expected user impact: smoother long-answer TUI and lower redraw CPU.
  2. P1: reduce activity visible-node clone/rebuild churn in streaming paths. Expected user impact: lower CPU during tool-heavy runs.
  3. P2: inspect startup session listing cost when many JSONL files exist; keep session semantics unchanged.
  4. P2: keep idle loop under observation with optional physical-terminal wakeup sample; PTY evidence shows low CPU and no P0 idle blocker.
  5. P3: process cleanup polling changes are riskier because they touch safety semantics; optimize only with process-tree regression coverage.

Before/after comparison method

  1. Use the same machine, branch base, and Rust profile, and the same terminal size for TUI checks.
  2. Run:
python3 scripts/profile_cpu.py --repo . --all --min-seconds 10
cargo test --release profile_cpu -- --ignored --nocapture
  1. Profile the changed area with a platform profiler:
sample <pid> 10 -file target/profiling/issue-48/<scenario>.sample.txt
# or Linux:
perf record -F 99 -g -- cargo test --release <scenario> -- --ignored --nocapture
  1. Compare baseline table fields: scenario, date/time, machine/OS/arch, Rust version/profile, command, duration/iterations, primary metric, result, artifact path, notes.
  2. Compare hotspot table fields: scenario, source file, function/symbol, metric type, metric value, profiler artifact, impact, confidence, follow-up priority.
  3. Report delta as (after - before) / before, plus whether profiler top symbols moved away from target function.

Optional live-provider profiling

Live provider profiling is not part of the default workflow. Skip it unless credentials and network are intentionally available. Do not store provider captures, bearer-style headers, provider secret strings, account identifiers, authorization codes, or secret payloads in fixtures or artifacts.

Edit this page on GitHub ↗