4.2 KiB
Brief: Tauri live-app benchmark and profiling
Audience: the next agent/session taking on desktop-app (live Tauri + CEF)
profiling. The Rust-core library side is done and documented in
library-benchmarking.md; this brief covers what
to build for the shipped desktop app, what already exists, and what to reuse.
Goal
Bring the desktop app to the same standard the core now has: named, repeatable scenarios; fresh-process repeats with median aggregation; JSON results; pass/fail budget gates; and an escalation path for attribution. The app is a process family (Tauri host + CEF helpers + utility/GPU/renderer processes + node/python runtime children), so every measurement must be family-wide, not single-pid.
What already exists (reuse, do not rebuild)
app/src-tauri/profiling/— an offline Tauri process-family profiler (own small crate:src/main.rs~813 lines, README) added in commitce6cd2291. Start here; extend it rather than writing a new sampler.src/openhuman/proc_metrics/— RSS/peak/threads/CPU-ms/fds sampling plustree.rs(descendant process-tree walker, macOSproc_listchildpids- Linux
/procppid walk). The tree sampler is exactly what family-wide measurement needs.
- Linux
scripts/profile/— the driver-script pattern (build → N fresh runs → jq medians → summary.md + gate exit code). Copylibrary-bench.sh's shape for anapp-bench.sh.- JSON schema v2 (
library-profileoutput) — reuse the field names (baseline/settled/peak_rss_kib/checkpoints[]/budget) so existing aggregation and future CI tooling work on both suites. - Env-var conventions —
OPENHUMAN_PROFILE_*knobs,HOLD_SECS-style inspection points.
Prior findings to build on (2026-07-21 session)
| Finding | Number |
|---|---|
| Full desktop process family | 1,207-1,440 MiB |
| CEF prewarm cost | ~86 MiB (disable/short-lived candidate) |
| spaCy cost | ~146 MiB (lazy-init candidate) |
| Rust core share of the family | ~40-50 MiB |
The gap between the ~50 MiB core and the ~1.2-1.4 GiB family is the entire story: CEF/renderer processes, prewarm policy, spaCy, and shell-side polling.
Suggested scenarios
- cold-boot — launch to interactive UI; family RSS + wall time, checkpointed (host start, core ready, CEF first frame, UI route mounted).
- idle-drift — 10-30 min idle; family RSS + CPU sampled continuously.
This is where scanner polling, heartbeat, accessibility probes, and
osascriptprobes show up (keep them event-driven per prior findings). - chat-turn-e2e — one full chat turn through the real UI (drive via CDP
on the CEF debug port or the Appium harness in
openhuman/e2e/); compare against the core-onlyagent-turnbaseline to attribute shell overhead. - webview-cycle — open/close provider webviews (N cycles); CEF child process lifecycle, leak check on repeat.
- prewarm-matrix — CEF prewarm on/off × spaCy on/off, reproducing and pinning the prior session's ~86/~146 MiB findings as a regression gate.
- overlay-surfaces — mascot/notch/companion windows up vs down.
Method notes
- Family enumeration: union of the Tauri host's descendant tree (use
proc_metrics::tree) plus CEF helper processes, which may re-parent — match by bundle path/name asapp/src-tauri/profilingalready does. - Sum-RSS double-counts shared CEF framework pages across helpers; on macOS
record
footprintoutput alongside ps-style sums (the instances driver inscripts/profile/library-instances.shshows the pattern and caveat wording); on Linux use PSS. - Drive the UI mechanically, not by hand: CDP against CEF (
:19222per the e2e harness) or the WDIO/Appium specs. Every scenario must run unattended. - Gate suggestion: family budget per scenario (e.g. cold-boot ≤ X MiB,
idle-drift slope ≈ 0), same PASS/FAIL summary style as
library-fleet.sh.
Definition of done
scripts/profile/app-bench.sh(or equivalent) running the scenarios above unattended with median aggregation and gates.- Baselines recorded in a doc table (like
library-benchmarking.md). - The prewarm/spaCy findings converted from one-off observations into standing regression gates.