Skip to content

Commit 067c5f9

Browse files
hoxyqfacebook-github-bot
authored andcommitted
Record Event Loop tasks (facebook#49436)
Summary: Pull Request resolved: facebook#49436 # Changelog: [Internal] We will record event loop ticks and register corresponding `"RunTask"` Trace Event with our Trace Event engine. Since this is hot path, I've added some gating under macros that are being used for Fusebox initialization. There are also plans to add a public method to `PerformanceTracer` to get tracing status, so we could avoid cost of serialization / saving timestamps if trace is not being recorded. I believe rubennorte had plans on this, we will add it on top of that. > Q: Why not add this to TraceSection? Long-term, we will have a solution that will be one layer above TraceSection and this `EventLoopTaskReporterRAII`, it is risky now to modify existing `TraceSection` and rely on event names and attempt to map them to Trace Events. Reviewed By: rubennorte Differential Revision: D69399955 fbshipit-source-id: b26ac0c376e7dcb5755f36a27bf00dcca6cbff60
1 parent bf6852d commit 067c5f9

File tree

7 files changed

+113
-1
lines changed

7 files changed

+113
-1
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include "EventLoopTaskReporter.h"
9+
10+
#if defined(REACT_NATIVE_DEBUGGER_ENABLED)
11+
#include "PerformanceTracer.h"
12+
#endif
13+
14+
namespace facebook::react::jsinspector_modern::tracing {
15+
16+
#if defined(REACT_NATIVE_DEBUGGER_ENABLED)
17+
namespace {
18+
19+
inline uint64_t formatTimePointToUnixTimestamp(
20+
std::chrono::steady_clock::time_point timestamp) {
21+
return std::chrono::duration_cast<std::chrono::microseconds>(
22+
timestamp.time_since_epoch())
23+
.count();
24+
}
25+
26+
} // namespace
27+
28+
EventLoopTaskReporter::EventLoopTaskReporter()
29+
: startTimestamp_(std::chrono::steady_clock::now()) {}
30+
31+
EventLoopTaskReporter::~EventLoopTaskReporter() {
32+
PerformanceTracer& performanceTracer = PerformanceTracer::getInstance();
33+
if (performanceTracer.isTracing()) {
34+
auto end = std::chrono::steady_clock::now();
35+
performanceTracer.reportEventLoopTask(
36+
formatTimePointToUnixTimestamp(startTimestamp_),
37+
formatTimePointToUnixTimestamp(end));
38+
}
39+
}
40+
41+
#else
42+
43+
EventLoopTaskReporter::EventLoopTaskReporter() {}
44+
45+
EventLoopTaskReporter::~EventLoopTaskReporter() {}
46+
47+
#endif
48+
49+
} // namespace facebook::react::jsinspector_modern::tracing
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <chrono>
11+
12+
namespace facebook::react::jsinspector_modern::tracing {
13+
14+
struct EventLoopTaskReporter {
15+
public:
16+
EventLoopTaskReporter();
17+
18+
EventLoopTaskReporter(const EventLoopTaskReporter&) = delete;
19+
EventLoopTaskReporter(EventLoopTaskReporter&&) = delete;
20+
EventLoopTaskReporter& operator=(const EventLoopTaskReporter&) = delete;
21+
EventLoopTaskReporter& operator=(EventLoopTaskReporter&&) = delete;
22+
23+
~EventLoopTaskReporter();
24+
25+
private:
26+
#if defined(REACT_NATIVE_DEBUGGER_ENABLED)
27+
std::chrono::steady_clock::time_point startTimestamp_;
28+
#endif
29+
};
30+
31+
} // namespace facebook::react::jsinspector_modern::tracing

packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,27 @@ void PerformanceTracer::reportThread(uint64_t id, const std::string& name) {
213213
});
214214
}
215215

216+
void PerformanceTracer::reportEventLoopTask(uint64_t start, uint64_t end) {
217+
if (!tracing_) {
218+
return;
219+
}
220+
221+
std::lock_guard lock(mutex_);
222+
if (!tracing_) {
223+
return;
224+
}
225+
226+
buffer_.push_back(TraceEvent{
227+
.name = "RunTask",
228+
.cat = "disabled-by-default-devtools.timeline",
229+
.ph = 'X',
230+
.ts = start,
231+
.pid = oscompat::getCurrentProcessId(),
232+
.tid = oscompat::getCurrentThreadId(),
233+
.dur = end - start,
234+
});
235+
}
236+
216237
folly::dynamic PerformanceTracer::serializeTraceEvent(TraceEvent event) const {
217238
folly::dynamic result = folly::dynamic::object;
218239

packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ class PerformanceTracer {
9494
*/
9595
void reportJavaScriptThread();
9696

97+
/**
98+
* Record an Event Loop tick, which will be represented as an Event Loop task
99+
* on a timeline view and grouped with JavaScript samples.
100+
*/
101+
void reportEventLoopTask(uint64_t start, uint64_t end);
102+
97103
private:
98104
PerformanceTracer();
99105
PerformanceTracer(const PerformanceTracer&) = delete;

packages/react-native/ReactCommon/react/renderer/runtimescheduler/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ target_link_libraries(react_renderer_runtimescheduler
2929
react_timing
3030
react_utils
3131
react_featureflags
32-
runtimeexecutor)
32+
runtimeexecutor
33+
jsinspector_tracing)

packages/react-native/ReactCommon/react/renderer/runtimescheduler/React-runtimescheduler.podspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Pod::Spec.new do |s|
6464
s.dependency "React-performancetimeline"
6565
s.dependency "React-rendererconsistency"
6666
add_dependency(s, "React-debug")
67+
add_dependency(s, "React-jsinspectortracing", :framework_name => 'jsinspector_moderntracing')
6768

6869
depend_on_js_engine(s)
6970
end

packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "SchedulerPriorityUtils.h"
1010

1111
#include <cxxreact/TraceSection.h>
12+
#include <jsinspector-modern/tracing/EventLoopTaskReporter.h>
1213
#include <react/featureflags/ReactNativeFeatureFlags.h>
1314
#include <react/renderer/consistency/ScopedShadowTreeRevisionLock.h>
1415
#include <react/timing/primitives.h>
@@ -308,6 +309,8 @@ void RuntimeScheduler_Modern::runEventLoopTick(
308309
Task& task,
309310
RuntimeSchedulerTimePoint taskStartTime) {
310311
TraceSection s("RuntimeScheduler::runEventLoopTick");
312+
[[maybe_unused]] jsinspector_modern::tracing::EventLoopTaskReporter
313+
performanceReporter;
311314

312315
ScopedShadowTreeRevisionLock revisionLock(
313316
shadowTreeRevisionConsistencyManager_);

0 commit comments

Comments
 (0)