You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
chore: Update btrace-perfetto skill with debug builds and trace comparison
Prefer debug builds for richer tracing instrumentation (Handler,
MessageQueue, Lock slices). Add trace_processor prerequisite for local
querying. Add Step 6 with SQL queries and comparison table generation.
Include sampling rate reference and additional troubleshooting entries.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Capture Perfetto traces with btrace 3.0 on a connected Android device, optionally comparing two branches. Opens results in Perfetto UI with a prefilled SQL query.
10
+
Capture Perfetto traces with btrace 3.0 on a connected Android device, optionally comparing two branches. Opens results in Perfetto UI with a prefilled SQL query. After capture, query traces locally with `trace_processor` to compute comparison stats.
In `sentry-samples/sentry-samples-android/proguard-rules.pro`, add:
82
+
Only needed when building release. In `sentry-samples/sentry-samples-android/proguard-rules.pro`, add:
79
83
80
84
```
81
85
-keep class com.bytedance.rheatrace.** { *; }
@@ -86,7 +90,13 @@ The first rule prevents R8 from stripping btrace's HTTP server classes (fails wi
86
90
87
91
## Step 3: Build and Install
88
92
89
-
Always use release builds for tracing — debug builds have StrictMode, debuggable overhead, and no R8 optimizations, which skew results.
93
+
Prefer **debug builds** — they provide richer tracing instrumentation (Handler, MessageQueue, Monitor:Lock slices visible) which is essential for comparing internal SDK behavior. Use the default 1kHz btrace sampling rate for debug builds.
**Release builds** are useful when you need to measure real-world performance without StrictMode/debuggable overhead or with R8 optimizations. Require the ProGuard keep rules from step 2d. Use `-sampleInterval 333000` (333μs / 3kHz) for finer granularity since release code runs faster.
adb shell am start -n io.sentry.samples.android/.MainActivity
120
+
sleep 5
107
121
```
108
122
109
-
The app must be started AFTER `debug.rhea3.startWhenAppLaunch` is set, otherwise the trace server won't initialize.
123
+
The app must be started AFTER `debug.rhea3.startWhenAppLaunch` is set, otherwise the trace server won't initialize. The 5s sleep after launch gives the btrace HTTP server time to start.
110
124
111
125
### 4b: Play a sound to signal the user, then capture
112
126
113
127
Play a sound when tracing actually starts so the user knows to begin interacting. Pipe btrace output through a loop that triggers the sound on the "start tracing" line:
This ensures the sound is synchronized with the actual trace start, not an estimated delay.
125
-
126
129
```bash
127
130
java -jar tools/btrace/rhea-trace-shell.jar \
128
131
-a io.sentry.samples.android \
129
132
-t ${duration} \
130
133
-waitTraceTimeout 60 \
131
134
-o tools/btrace/traces/${branch_name}.pb \
132
-
sched
135
+
sched 2>&1|while IFS= read -r line;do
136
+
echo"$line"
137
+
if [[ "$line"==*"start tracing"* ]];then
138
+
afplay -v 1.5 /System/Library/Sounds/Ping.aiff &
139
+
fi
140
+
done
133
141
```
134
142
143
+
For release builds with finer sampling, add `-sampleInterval 333000`.
144
+
135
145
Do NOT use the `-r` flag — it fails to resolve the launcher activity because LeakCanary registers a second one. Launch the app manually in step 4a instead.
136
146
137
147
### 4c: Switch branches for comparison
@@ -147,7 +157,7 @@ When capturing a second branch:
147
157
```
148
158
2. Checkout the other branch
149
159
3. Pop the stash: `git stash pop`
150
-
4. Rebuild and install: `./gradlew :sentry-samples:sentry-samples-android:installRelease`
160
+
4. Rebuild and install (same variant — debug or release — as the first branch)
151
161
5. Repeat steps 4a and 4b with a different output filename
152
162
6. Switch back to the original branch and restore files
153
163
@@ -185,6 +195,76 @@ WHERE s.name GLOB '*SentryWindowCallback.dispatch*'
185
195
ORDER BYs.ts
186
196
```
187
197
198
+
## Step 6: Query and Compare Traces
199
+
200
+
After capturing both branches, use `trace_processor` to compute comparison stats locally.
201
+
202
+
### Basic stats query
203
+
204
+
For each trace file, run:
205
+
206
+
```bash
207
+
/tmp/trace_processor -Q "
208
+
WITH events AS (
209
+
SELECT s.dur / 1e6 as dur_ms FROM slice s
210
+
WHERE s.name GLOB '*${METHOD_GLOB}*' AND s.dur > 0
211
+
ORDER BY s.dur
212
+
)
213
+
SELECT COUNT(*) as count,
214
+
ROUND(AVG(dur_ms), 4) as avg_ms,
215
+
ROUND((SELECT dur_ms FROM events LIMIT 1 OFFSET (SELECT COUNT(*)/2 FROM events)), 4) as median_ms,
216
+
ROUND(MIN(dur_ms), 4) as min_ms,
217
+
ROUND(MAX(dur_ms), 4) as max_ms
218
+
FROM events
219
+
" tools/btrace/traces/${trace_file}.pb
220
+
```
221
+
222
+
Replace `${METHOD_GLOB}` with the method pattern to compare (e.g. `SentryGestureDetector.onTouchEvent`, `SentryWindowCallback.dispatchTouchEvent`).
223
+
224
+
### Finding child calls (debug builds)
225
+
226
+
To find what happens inside a method (e.g. Handler calls, lock acquisitions):
227
+
228
+
```bash
229
+
/tmp/trace_processor -Q "
230
+
WITH RECURSIVE descendants(id, depth) AS (
231
+
SELECT s.id, 0 FROM slice s WHERE s.name GLOB '*${PARENT_METHOD}*'
232
+
UNION ALL
233
+
SELECT s.id, d.depth + 1 FROM slice s JOIN descendants d ON s.parent_id = d.id WHERE d.depth < 10
234
+
)
235
+
SELECT s.name, COUNT(*) as count, ROUND(AVG(s.dur / 1e6), 3) as avg_ms
236
+
FROM slice s JOIN descendants d ON s.id = d.id
237
+
WHERE d.depth > 0
238
+
GROUP BY s.name ORDER BY count DESC
239
+
LIMIT 20
240
+
" tools/btrace/traces/${trace_file}.pb
241
+
```
242
+
243
+
### Build the comparison table
244
+
245
+
Run the stats query on both trace files, then present a markdown table:
246
+
247
+
```
248
+
| Metric | Branch A | Branch B | Delta |
249
+
|--------|----------|----------|-------|
250
+
| Count | ... | ... | |
251
+
| Average| ... | ... | -X% |
252
+
| Median | ... | ... | -X% |
253
+
| Max | ... | ... | -X% |
254
+
```
255
+
256
+
Compute delta as `(branchA - branchB) / branchB * 100`. Negative means branch A is faster.
Higher sampling rates capture shorter method calls but add CPU overhead which can skew results. For most comparisons, the default 1kHz is sufficient.
267
+
188
268
## Cleanup
189
269
190
270
After tracing is complete, remind the user that the btrace integration changes to the sample app should NOT be committed. The `tools/btrace/` directory is gitignored.
@@ -200,3 +280,5 @@ After tracing is complete, remind the user that the btrace integration changes t
200
280
| Empty jar file (0 bytes) | Download from Maven Central (`repo1.maven.org`), not `oss.sonatype.org`|
201
281
|`FileNotFoundException` on sampling download | App was already running when properties were set; force-stop and relaunch |
202
282
|`SocketException: Unexpected end of file` in release builds | R8 stripped btrace classes; add `-keep class com.bytedance.rheatrace.** { *; }` to proguard-rules.pro |
283
+
| Stale port from previous session | Run `adb shell "rm -rf /storage/emulated/0/Android/data/io.sentry.samples.android/files/rhea-port"` before launching |
284
+
| Most `onTouchEvent` durations are 0ms | Increase sampling rate with `-sampleInterval 333000` (3kHz) |
0 commit comments