Systrace wraps JavaScript in named markers for Android's system trace: beginEvent() and endEvent() around synchronous code, beginAsyncEvent() and endAsyncEvent() across awaits, and counterEvent() for a value over time. Every call first checks isEnabled(), which needs a native hook named nativeTraceIsTracing:
console.log('Systrace.isEnabled():', Systrace.isEnabled(),
'| nativeTraceBeginSection:', typeof (globalThis as any).nativeTraceBeginSection);
Systrace.beginEvent('sort 5000 books');
const t0 = performance.now();
catalog(5000).sort((a, b) => a.title.localeCompare(b.title));
Systrace.endEvent();LOG Systrace.isEnabled(): false | nativeTraceBeginSection: undefined LOG sorted in 3187 ms
This build has no such hook, so the markers are harmless no-ops even while a trace records. The system trace itself works: Perfetto 440,880 , Android's system tracer since Android 9, recorded ten seconds while the button was pressed:
adb shell perfetto -o /data/misc/perfetto-traces/booknest.pftrace -t 10s \
-a com.anonymous.booknest sched gfx view am
adb pull /data/misc/perfetto-traces/booknest.pftrace... [809.610] perfetto_cmd.cc:1210 Wrote 1618333 bytes into /data/misc/perfetto-traces/... /data/misc/perfetto-traces/booknest.pftrace: 1 file pulled, 0 skipped. ...
Open the file at ui.perfetto.dev (https://ui.perfetto.dev 440,880 ) and find the JavaScript thread, mqt_v_js, beside the main thread. adb shell dumpsys gfxinfo <package> gives quick frame statistics without a trace; here it reported 19 of 24 frames janky, a debug build on a loaded emulator, so measure release builds on a phone before acting. For JavaScript itself, React Native DevTools 36,878 (React Native DevTools) points straight at costs such as this sort, whose localeCompare() calls took three seconds for 5,000 titles.