@houwert/conductor 0.27.2 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,21 +1,116 @@
1
1
  ---
2
2
  name: conductor-profiler
3
- description: Profile a running app's CPU, memory, and React render performance with the conductor CLI, and read crash reports. Use when investigating slowness, jank, memory growth or leaks, excessive React re-renders, or when an app has crashed and you need the crash report.
3
+ description: Profile a running app's frame timing, input latency, JS CPU, native CPU, memory and React renders with the conductor CLI, and read crash reports. Use when investigating jank or sluggishness, slow navigation, input lag on TV remotes, memory growth or leaks, GC pauses, excessive React re-renders, or when an app has crashed and you need the crash report.
4
4
  ---
5
5
 
6
6
  # Conductor — profiling & crashes
7
7
 
8
8
  Measure a running app's performance and inspect crashes.
9
9
 
10
- ## Profiling
10
+ ## Pick the right instrument
11
+
12
+ | Symptom the user reports | Measure with |
13
+ |---|---|
14
+ | "Scrolling/navigation is janky" | `profile frames` (Android) — objective jank rate and per-phase attribution |
15
+ | "I press a key and it takes a moment" | `press-key <key> --measure --repeat 20` |
16
+ | "It's slow, where does the time go?" (JS) | `profile js record --duration 10` |
17
+ | "It's slow, where does the time go?" (native) | `profile cpu --duration 10 --report` |
18
+ | "Which component re-renders on every input?" | `profile react start` → interact → `profile react stop` |
19
+ | "Memory grows / it stutters periodically" | `profile memory --track 30` |
20
+
21
+ `profile frames`, `profile cpu` and `profile memory` work on **release builds**
22
+ and on real hardware. `profile js` and `profile react` attach over Metro, so
23
+ they need a dev/profiling build.
24
+
25
+ ## Frame timing & jank (Android, incl. Fire TV / Android TV)
26
+
27
+ | Command | Purpose |
28
+ |---|---|
29
+ | `conductor profile frames reset [<appId>]` | Zero the gfxinfo counters |
30
+ | `conductor profile frames report [<appId>]` | Jank rate, p50–p99 frame times, per-phase breakdown |
31
+ | `conductor profile frames report --track <s> [--interval <ms>]` | Reset, sample for N seconds, then report |
32
+ | `conductor profile frames report --save-baseline <name>` / `--diff <name>` / `--baselines` | Save and compare runs |
33
+
34
+ Reads `dumpsys gfxinfo <pkg> framestats`, so it needs no instrumentation.
35
+
36
+ **On TV, be deliberate about who is driving.** `press-key` injects with
37
+ `adb shell input keyevent`, which spawns a JVM on the device (~713ms) beside
38
+ the frames you are measuring. Mobile's answer — fling and measure the momentum
39
+ scroll — does not exist on TV, where focus moves one step per press and stops.
40
+ So a navigation capture is always partly a measurement of the harness. Idle
41
+ screens, load settles, cold start and self-running animations are clean; for
42
+ navigation, prefer asking a human to drive the physical remote during the
43
+ window (the command announces the window on stderr for exactly this), and treat
44
+ a divergence between human-driven and automated numbers as the harness.
45
+
46
+ Not available on `vega` — but a **physical Fire TV Stick runs Fire OS
47
+ (Android)** over adb and works fine.
48
+
49
+ Attribute jank by comparing each phase's p95 against its p50: `vsyncDelay` means
50
+ the UI thread was blocked elsewhere, `traversal` means measure/layout,
51
+ `draw` means display-list recording, `issueDraw` means render-thread/GPU.
52
+
53
+ ## Input latency
54
+
55
+ | Command | Purpose |
56
+ |---|---|
57
+ | `conductor press-key <key> --measure` | Time the app's response to the press |
58
+ | `conductor press-key <key> --measure --repeat <n>` | Take n samples and report a distribution |
59
+ | `--sequence <k1,k2>` | Cycle keys so repeats oscillate instead of drifting across the UI |
60
+ | `--timeout <ms>` / `--poll-interval <ms>` / `--settle <ms>` | Give-up time; poll delay; render time to allow |
61
+
62
+ Read `outcome` per sample before the aggregates. `moved` is a measurement;
63
+ `unchanged` means focus queries kept working and the app simply declined to move
64
+ (a rail edge, or a key this screen ignores) and is **not** a hang;
65
+ `query-failed` is the one that suggests something is wedged.
66
+
67
+ `--repeat` is not repeated measurement of one event — pressing Right twenty
68
+ times walks twenty different transitions. Read `byTransition` before the
69
+ aggregate, or use `--sequence` to oscillate between two positions.
70
+
71
+ On Android `pressToFrame` is derived from device-side clocks and is the figure
72
+ to trust. `focusChange` is bounded by how long one hierarchy dump takes, and a
73
+ `round-trip-bound` note fires when that floor dominates. gfxinfo's own
74
+ `inputLatency` appears only when the device populates `NewestInputEvent` — it
75
+ does on a Fire TV Stick, it never does on an NVIDIA SHIELD — so treat it as a
76
+ bonus, never as something whose absence means no input occurred.
77
+
78
+ ## JS CPU (Hermes sampling profiler)
79
+
80
+ | Command | Purpose |
81
+ |---|---|
82
+ | `conductor profile js record --duration <s> [--top n] [--out <path>]` | Sample, then rank functions by self time with `file:line` |
83
+ | `conductor profile js start` / `conductor profile js stop [--top n]` | Same, bracketing a flow you drive in between |
84
+
85
+ Writes a raw `.cpuprofile` you can load in Chrome DevTools (Performance → Load
86
+ profile) or convert with `npx hermes-profile-transformer`.
87
+
88
+ ## Native CPU
11
89
 
12
90
  | Command | Purpose |
13
91
  |---|---|
14
- | `conductor profile cpu --duration <s> [--out <path>]` | Record a CPU trace (iOS: xctrace, Android: simpleperf) |
15
- | `conductor profile memory --track <s> [--interval ms] [<appId>]` | Sample memory for N seconds, report deltas |
16
- | `conductor profile react start` / `profile react stop [--top N]` | Install a React commit-profiler hook, then summarize captured commits |
92
+ | `conductor profile cpu --duration <s> [--out <path>]` | Record a trace (iOS: xctrace, Android: simpleperf) |
93
+ | `conductor profile cpu --duration <s> --report [--top n]` | Android: also return a ranked symbol table |
17
94
 
18
- ## Memory
95
+ Without `--report` on Android you get a binary `perf.data` you cannot read —
96
+ pass `--report` when you need the answer rather than the artefact.
97
+
98
+ ## React renders
99
+
100
+ | Command | Purpose |
101
+ |---|---|
102
+ | `conductor profile react start [--max-commits n] [--max-components n]` | Install the commit-profiler hook |
103
+ | `conductor profile react stop [--top n] [--timeline] [--json]` | Stop and rank components by self time |
104
+
105
+ Sort key is `selfMs`, which is additive across components; `totalMs` is
106
+ subtree-inclusive and double-counts parents. `--json` includes the per-commit
107
+ timeline (timestamps + durations) so you can line a jank spike up with an input;
108
+ `--timeline` adds per-commit component detail. If either buffer overflows the
109
+ output says `truncated: true` with the dropped counts — raise the limits rather
110
+ than trusting the tail. On a release build it fails with a clear message instead
111
+ of reporting zeroes.
112
+
113
+ ## Memory & GC
19
114
 
20
115
  | Command | Purpose |
21
116
  |---|---|
@@ -24,10 +119,17 @@ Measure a running app's performance and inspect crashes.
24
119
  | `conductor memory --leaks` | Run leak detection (iOS only; slow, can pause the app) |
25
120
  | `conductor memory --save <name>` / `--diff <name>` / `--diff <name> --vs <other>` | Snapshot and diff memory reports |
26
121
  | `conductor memory --filter <regex>` / `--growth-only` / `--top <n>` | Narrow object/class tables (great for leak-hunting) |
122
+ | `conductor profile memory --track <s> [--interval <ms>]` | Sample over a window; on Android also reports heap growth and ART GC pause counts/durations |
27
123
 
28
124
  Typical leak hunt: `memory --save before`, exercise the screen, then
29
125
  `memory --diff before --growth-only`.
30
126
 
127
+ ## Repeatable benchmarking
128
+
129
+ `conductor run-flow <file> --benchmark --repeat <n> --json` runs the flow n
130
+ times and reports per-command p50/p90/stddev. Use it on TV, where single-run
131
+ variance is large enough to swamp the effect you're looking for.
132
+
31
133
  ## Crashes
32
134
 
33
135
  | Command | Purpose |
@@ -39,4 +141,10 @@ Typical leak hunt: `memory --save before`, exercise the screen, then
39
141
  ## Tips
40
142
 
41
143
  - Add `--json` to parse reports programmatically.
42
- - These commands can be slow or pause the app scope them with `--duration` / `--track` and avoid leaving `crashes tail` running.
144
+ - `--port` is auto-detected from the device for Metro-backed commands; pass it
145
+ explicitly only if that fails.
146
+ - These commands can be slow or pause the app — scope them with `--duration` /
147
+ `--track` and avoid leaving `crashes tail` running.
148
+ - An Android TV emulator is far faster than a Fire TV Stick. Trust frame timing
149
+ only from real hardware; emulators are fine for counts (React commits, GC
150
+ collections, JS self-time ranking).