Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 33 additions & 5 deletions perf-monitor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,39 @@ Only the fields you specify are overridden; others inherit from `[thresholds]`.

### Metrics

| Metric | Description |
| ---------------- | ---------------------------------------------------------- |
| CPU Avg / P95 | Process CPU usage normalized by logical CPU count (0-100%) |
| Memory Avg / P95 | Resident Set Size (RSS) in MB |
| Memory Growth | Last sample minus first sample (detects obvious leaks) |
CPU and memory are aggregated across the target process **and all of its
descendants** (children, grandchildren, ...). This matters for apps that
spawn helper / renderer processes (e.g. Tauri's WebView2 host on Windows,
Electron-style multi-process layouts) — measuring only the parent PID
would miss the bulk of the actual resource usage.

| Metric | Description |
| ---------------- | ------------------------------------------------------------------------ |
| CPU Avg / P95 | Aggregated CPU usage normalized by logical CPU count (0-100%) |
| Memory Avg / P95 | Aggregated Resident Set Size (RSS) in MB across the process tree |
| Memory Growth | Last sample minus first sample (detects obvious leaks) |

### Report sections

The text report (and the matching JSON output) is structured to make
CI logs easy to scan:

1. **Aggregated (process tree)** — avg / P95 / max across the parent +
descendants, with per-check `PASS` / `FAIL` against the configured
thresholds.
2. **Per-Process Breakdown** — one block per observed PID showing the
process name, how many sample ticks it appeared in, and its own
avg / max / P95 for CPU and RSS. The root process is listed first and
marked `(root)`; descendants follow in descending order of average CPU.
3. **Failure Reasons** — printed only when at least one threshold was
exceeded; enumerates exactly which checks failed and the offending
value vs. the threshold. The JSON output exposes the same list as a
`failure_reasons` array.

If the measurement aborts before any samples are collected (binary
crashed during warmup, etc.), the failure reason and the captured
child stderr are printed under a `=== Performance Test Failed ===`
banner so the cause is visible at the bottom of the CI log.

### Exit Code

Expand Down
5 changes: 4 additions & 1 deletion perf-monitor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ fn main() -> ExitCode {
}
}
Err(e) => {
eprintln!("Error: monitoring failed: {e}");
eprintln!();
eprintln!("=== Performance Test Failed ===");
eprintln!("Failure reason: monitoring aborted before metrics could be collected");
eprintln!("Details: {e}");
Comment on lines +77 to +78

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Failure reason text can be misleading for mid-run aborts

At Line 77, the message says metrics could not be collected, but aborts can also happen after some ticks. Use neutral wording (e.g., “monitoring aborted before completion”) to avoid misleading CI triage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@perf-monitor/src/main.rs` around lines 77 - 78, The failure message printed
by the eprintln! call is too specific ("monitoring aborted before metrics could
be collected") and can be misleading for mid-run aborts; update the first
eprintln! invocation used in main (the eprintln!("Failure reason: ...") line) to
neutral wording such as "Failure reason: monitoring aborted before completion"
(leave the separate eprintln!("Details: {e}") unchanged so the actual error is
still logged).

ExitCode::FAILURE
}
}
Expand Down
Loading
Loading