From 8698ecad185d0ab2b32cc9fcb9e83badb65890d6 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Thu, 27 Feb 2025 10:38:38 -0800 Subject: [PATCH] Emit synthetic Trace Events for non-bridgeless to fix trace representation (#49729) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/49729 # Changelog: [Internal] The only data source for non-bridgeless setup is JavaScript samples. Chrome DevTools frontend is built around an assumption that thread should have at least single timeline or user timing event to be represented on a timeline view. They do it for filtering out unnecessary workers threads and other. We will emit 2 synthetic Trace Events that should cover these requirements and recorded traces that contain only JavaScript samples should now be displayed correctly. This is where trace bounds are calculated - https://github.com/facebookexperimental/rn-chrome-devtools-frontend/blob/3adf51aa915c2deb26f5d373751a15b4d0c8f259/front_end/models/trace/handlers/MetaHandler.ts#L169-L173 Reviewed By: huntie Differential Revision: D70328681 fbshipit-source-id: 8eca0017d85de9ecbfb49074b439d5c4fee4aa56 --- .../tracing/PerformanceTracer.cpp | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp index 5691ee3ca90..a241f53737b 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp @@ -67,6 +67,21 @@ bool PerformanceTracer::stopTracing() { return false; } + // This is synthetic Trace Event, which should not be represented on a + // timeline. CDT is not using Profile or ProfileChunk events for determining + // trace timeline window, this is why trace that only contains JavaScript + // samples will be displayed as empty. We use this event to avoid that. + // This could happen for non-bridgeless apps, where Performance interface is + // not supported and no spec-compliant Event Loop implementation. + buffer_.push_back(TraceEvent{ + .name = "ReactNative-TracingStopped", + .cat = "disabled-by-default-devtools.timeline", + .ph = 'I', + .ts = getUnixTimestampOfNow(), + .pid = processId_, + .tid = oscompat::getCurrentThreadId(), + }); + performanceMeasureCount_ = 0; profileCount_ = 0; tracing_ = false; @@ -212,6 +227,20 @@ void PerformanceTracer::reportThread(uint64_t id, const std::string& name) { .tid = id, .args = folly::dynamic::object("name", name), }); + + // This is synthetic Trace Event, which should not be represented on a + // timeline. CDT will filter out threads that only have JavaScript samples and + // no timeline events or user timings. We use this event to avoid that. + // This could happen for non-bridgeless apps, where Performance interface is + // not supported and no spec-compliant Event Loop implementation. + buffer_.push_back(TraceEvent{ + .name = "ReactNative-ThreadRegistered", + .cat = "disabled-by-default-devtools.timeline", + .ph = 'I', + .ts = 0, + .pid = processId_, + .tid = id, + }); } uint16_t PerformanceTracer::reportRuntimeProfile(