Skip to content

Commit 7d5dfe4

Browse files
hoxyqfacebook-github-bot
authored andcommitted
Use HighResTimeStamp (facebook#51454)
Summary: Pull Request resolved: facebook#51454 # Changelog: [Internal] There are multiple changes: 1. `PerformanceTracer` class, `TraceEvent` struct are moved to `tracing` namespace. These are parts of the Tracing subsystems of the jsinspector, this should bring more clarity and make things more explicit. 2. Added `Timing.h` class which defines conversion logic from `HighResTimeStamp` to absolute units that are expected by CDP. 3. `PerformanceTracer` will receive timestamps for Performance Web API entries in `HighResTimeStamp`. Also, we will explicilty define a Tracking Clock time origin that will be epoch of the `steady_clock`. This aligns with the approach in Chromium and saves us from aligning custom DOMHighResTimeStamps that can be specified in performance.mark / performance.measure calls: these should not extend the timeline window. I've confirmed that this is the current behavior in Chromium. Differential Revision: D74892330
1 parent 818dc98 commit 7d5dfe4

16 files changed

+163
-123
lines changed

packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ RuntimeTargetController::collectSamplingProfile() {
179179

180180
void RuntimeTarget::registerForTracing() {
181181
jsExecutor_([](auto& /*runtime*/) {
182-
PerformanceTracer::getInstance().reportJavaScriptThread();
182+
tracing::PerformanceTracer::getInstance().reportJavaScriptThread();
183183
});
184184
}
185185

packages/react-native/ReactCommon/jsinspector-modern/TracingAgent.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
4444
}
4545

4646
bool correctlyStartedPerformanceTracer =
47-
PerformanceTracer::getInstance().startTracing();
47+
tracing::PerformanceTracer::getInstance().startTracing();
4848

4949
if (!correctlyStartedPerformanceTracer) {
5050
frontendChannel_(cdp::jsonError(
@@ -56,7 +56,7 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
5656
}
5757

5858
instanceAgent_->startTracing();
59-
instanceTracingStartTimestamp_ = std::chrono::steady_clock::now();
59+
instanceTracingStartTimestamp_ = HighResTimeStamp::now();
6060
frontendChannel_(cdp::jsonResult(req.id));
6161

6262
return true;
@@ -73,7 +73,8 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
7373

7474
instanceAgent_->stopTracing();
7575

76-
PerformanceTracer& performanceTracer = PerformanceTracer::getInstance();
76+
tracing::PerformanceTracer& performanceTracer =
77+
tracing::PerformanceTracer::getInstance();
7778
bool correctlyStopped = performanceTracer.stopTracing();
7879
if (!correctlyStopped) {
7980
frontendChannel_(cdp::jsonError(

packages/react-native/ReactCommon/jsinspector-modern/TracingAgent.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include "InstanceAgent.h"
1212

1313
#include <jsinspector-modern/cdp/CdpJson.h>
14+
#include <jsinspector-modern/tracing/Timing.h>
15+
#include <react/timing/primitives.h>
1416

1517
namespace facebook::react::jsinspector_modern {
1618

@@ -54,9 +56,10 @@ class TracingAgent {
5456

5557
/**
5658
* Timestamp of when we started tracing of an Instance, will be used as a
57-
* a start of JavaScript samples recording.
59+
* a start of JavaScript samples recording and as a time origin for the events
60+
* in this trace.
5861
*/
59-
std::chrono::steady_clock::time_point instanceTracingStartTimestamp_;
62+
HighResTimeStamp instanceTracingStartTimestamp_;
6063
};
6164

6265
} // namespace facebook::react::jsinspector_modern

packages/react-native/ReactCommon/jsinspector-modern/tracing/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ target_include_directories(jsinspector_tracing PUBLIC ${REACT_COMMON_DIR})
1919
target_link_libraries(jsinspector_tracing
2020
folly_runtime
2121
oscompat
22+
react_timing
2223
)
2324
target_compile_reactnative_options(jsinspector_tracing PRIVATE)
2425
target_compile_options(jsinspector_tracing PRIVATE -Wpedantic)

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

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,21 @@
1414
namespace facebook::react::jsinspector_modern::tracing {
1515

1616
#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
2717

2818
EventLoopReporter::EventLoopReporter(EventLoopPhase phase)
29-
: startTimestamp_(std::chrono::steady_clock::now()), phase_(phase) {}
19+
: startTimestamp_(HighResTimeStamp::now()), phase_(phase) {}
3020

3121
EventLoopReporter::~EventLoopReporter() {
3222
PerformanceTracer& performanceTracer = PerformanceTracer::getInstance();
3323
if (performanceTracer.isTracing()) {
34-
auto end = std::chrono::steady_clock::now();
24+
auto end = HighResTimeStamp::now();
3525
switch (phase_) {
3626
case EventLoopPhase::Task:
37-
performanceTracer.reportEventLoopTask(
38-
formatTimePointToUnixTimestamp(startTimestamp_),
39-
formatTimePointToUnixTimestamp(end));
27+
performanceTracer.reportEventLoopTask(startTimestamp_, end);
4028
break;
4129

4230
case EventLoopPhase::Microtasks:
43-
performanceTracer.reportEventLoopMicrotasks(
44-
formatTimePointToUnixTimestamp(startTimestamp_),
45-
formatTimePointToUnixTimestamp(end));
31+
performanceTracer.reportEventLoopMicrotasks(startTimestamp_, end);
4632
break;
4733

4834
default:

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77

88
#pragma once
99

10-
#include <chrono>
10+
#if defined(REACT_NATIVE_DEBUGGER_ENABLED)
11+
#include <react/timing/primitives.h>
12+
#endif
1113

1214
namespace facebook::react::jsinspector_modern::tracing {
1315

@@ -29,7 +31,7 @@ struct EventLoopReporter {
2931

3032
private:
3133
#if defined(REACT_NATIVE_DEBUGGER_ENABLED)
32-
std::chrono::steady_clock::time_point startTimestamp_;
34+
HighResTimeStamp startTimestamp_;
3335
EventLoopPhase phase_;
3436
#endif
3537
};

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

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#include "PerformanceTracer.h"
9+
#include "Timing.h"
910

1011
#include <oscompat/OSCompat.h>
1112

@@ -14,17 +15,7 @@
1415
#include <array>
1516
#include <mutex>
1617

17-
namespace facebook::react::jsinspector_modern {
18-
19-
namespace {
20-
21-
uint64_t getUnixTimestampOfNow() {
22-
return std::chrono::duration_cast<std::chrono::microseconds>(
23-
std::chrono::steady_clock::now().time_since_epoch())
24-
.count();
25-
}
26-
27-
} // namespace
18+
namespace facebook::react::jsinspector_modern::tracing {
2819

2920
PerformanceTracer& PerformanceTracer::getInstance() {
3021
static PerformanceTracer tracer;
@@ -52,7 +43,7 @@ bool PerformanceTracer::startTracing() {
5243
.name = "TracingStartedInPage",
5344
.cat = "disabled-by-default-devtools.timeline",
5445
.ph = 'I',
55-
.ts = getUnixTimestampOfNow(),
46+
.ts = HighResTimeStamp::now(),
5647
.pid = processId_,
5748
.tid = oscompat::getCurrentThreadId(),
5849
.args = folly::dynamic::object("data", folly::dynamic::object()),
@@ -78,7 +69,7 @@ bool PerformanceTracer::stopTracing() {
7869
.name = "ReactNative-TracingStopped",
7970
.cat = "disabled-by-default-devtools.timeline",
8071
.ph = 'I',
81-
.ts = getUnixTimestampOfNow(),
72+
.ts = HighResTimeStamp::now(),
8273
.pid = processId_,
8374
.tid = oscompat::getCurrentThreadId(),
8475
});
@@ -117,7 +108,7 @@ void PerformanceTracer::collectEvents(
117108

118109
void PerformanceTracer::reportMark(
119110
const std::string_view& name,
120-
uint64_t start) {
111+
HighResTimeStamp start) {
121112
if (!tracing_) {
122113
return;
123114
}
@@ -139,8 +130,8 @@ void PerformanceTracer::reportMark(
139130

140131
void PerformanceTracer::reportMeasure(
141132
const std::string_view& name,
142-
uint64_t start,
143-
uint64_t duration,
133+
HighResTimeStamp start,
134+
HighResDuration duration,
144135
const std::optional<DevToolsTrackEntryPayload>& trackMetadata) {
145136
if (!tracing_) {
146137
return;
@@ -197,7 +188,7 @@ void PerformanceTracer::reportProcess(uint64_t id, const std::string& name) {
197188
.name = "process_name",
198189
.cat = "__metadata",
199190
.ph = 'M',
200-
.ts = 0,
191+
.ts = TRACING_TIME_ORIGIN,
201192
.pid = id,
202193
.tid = 0,
203194
.args = folly::dynamic::object("name", name),
@@ -222,7 +213,7 @@ void PerformanceTracer::reportThread(uint64_t id, const std::string& name) {
222213
.name = "thread_name",
223214
.cat = "__metadata",
224215
.ph = 'M',
225-
.ts = 0,
216+
.ts = TRACING_TIME_ORIGIN,
226217
.pid = processId_,
227218
.tid = id,
228219
.args = folly::dynamic::object("name", name),
@@ -237,13 +228,15 @@ void PerformanceTracer::reportThread(uint64_t id, const std::string& name) {
237228
.name = "ReactNative-ThreadRegistered",
238229
.cat = "disabled-by-default-devtools.timeline",
239230
.ph = 'I',
240-
.ts = 0,
231+
.ts = TRACING_TIME_ORIGIN,
241232
.pid = processId_,
242233
.tid = id,
243234
});
244235
}
245236

246-
void PerformanceTracer::reportEventLoopTask(uint64_t start, uint64_t end) {
237+
void PerformanceTracer::reportEventLoopTask(
238+
HighResTimeStamp start,
239+
HighResTimeStamp end) {
247240
if (!tracing_) {
248241
return;
249242
}
@@ -265,8 +258,8 @@ void PerformanceTracer::reportEventLoopTask(uint64_t start, uint64_t end) {
265258
}
266259

267260
void PerformanceTracer::reportEventLoopMicrotasks(
268-
uint64_t start,
269-
uint64_t end) {
261+
HighResTimeStamp start,
262+
HighResTimeStamp end) {
270263
if (!tracing_) {
271264
return;
272265
}
@@ -290,33 +283,36 @@ void PerformanceTracer::reportEventLoopMicrotasks(
290283
folly::dynamic PerformanceTracer::getSerializedRuntimeProfileTraceEvent(
291284
uint64_t threadId,
292285
uint16_t profileId,
293-
uint64_t eventUnixTimestamp) {
286+
HighResTimeStamp profileTimestamp) {
294287
// CDT prioritizes event timestamp over startTime metadata field.
295288
// https://fburl.com/lo764pf4
296289
return serializeTraceEvent(TraceEvent{
297290
.id = profileId,
298291
.name = "Profile",
299292
.cat = "disabled-by-default-v8.cpu_profiler",
300293
.ph = 'P',
301-
.ts = eventUnixTimestamp,
294+
.ts = profileTimestamp,
302295
.pid = processId_,
303296
.tid = threadId,
304297
.args = folly::dynamic::object(
305-
"data", folly ::dynamic::object("startTime", eventUnixTimestamp)),
298+
"data",
299+
folly ::dynamic::object(
300+
"startTime",
301+
highResTimeStampToTracingClockTimeStamp(profileTimestamp))),
306302
});
307303
}
308304

309305
folly::dynamic PerformanceTracer::getSerializedRuntimeProfileChunkTraceEvent(
310306
uint16_t profileId,
311307
uint64_t threadId,
312-
uint64_t eventUnixTimestamp,
308+
HighResTimeStamp chunkTimestamp,
313309
const tracing::TraceEventProfileChunk& traceEventProfileChunk) {
314310
return serializeTraceEvent(TraceEvent{
315311
.id = profileId,
316312
.name = "ProfileChunk",
317313
.cat = "disabled-by-default-v8.cpu_profiler",
318314
.ph = 'P',
319-
.ts = eventUnixTimestamp,
315+
.ts = chunkTimestamp,
320316
.pid = processId_,
321317
.tid = threadId,
322318
.args =
@@ -336,15 +332,15 @@ folly::dynamic PerformanceTracer::serializeTraceEvent(
336332
result["name"] = event.name;
337333
result["cat"] = event.cat;
338334
result["ph"] = std::string(1, event.ph);
339-
result["ts"] = event.ts;
335+
result["ts"] = highResTimeStampToTracingClockTimeStamp(event.ts);
340336
result["pid"] = event.pid;
341337
result["tid"] = event.tid;
342338
result["args"] = event.args;
343339
if (event.dur.has_value()) {
344-
result["dur"] = event.dur.value();
340+
result["dur"] = highResDurationToTracingClockDuration(event.dur.value());
345341
}
346342

347343
return result;
348344
}
349345

350-
} // namespace facebook::react::jsinspector_modern
346+
} // namespace facebook::react::jsinspector_modern::tracing

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@
1111
#include "TraceEvent.h"
1212
#include "TraceEventProfile.h"
1313

14-
#include <folly/dynamic.h>
14+
#include <react/timing/primitives.h>
1515

16+
#include <folly/dynamic.h>
1617
#include <functional>
1718
#include <mutex>
1819
#include <optional>
1920
#include <vector>
2021

21-
namespace facebook::react::jsinspector_modern {
22+
namespace facebook::react::jsinspector_modern::tracing {
2223

2324
// TODO: Review how this API is integrated into jsinspector_modern (singleton
2425
// design is copied from earlier FuseboxTracer prototype).
@@ -65,7 +66,7 @@ class PerformanceTracer {
6566
*
6667
* See https://w3c.github.io/user-timing/#mark-method.
6768
*/
68-
void reportMark(const std::string_view& name, uint64_t start);
69+
void reportMark(const std::string_view& name, HighResTimeStamp start);
6970

7071
/**
7172
* Record a `Performance.measure()` event - a labelled duration. If not
@@ -75,8 +76,8 @@ class PerformanceTracer {
7576
*/
7677
void reportMeasure(
7778
const std::string_view& name,
78-
uint64_t start,
79-
uint64_t duration,
79+
HighResTimeStamp start,
80+
HighResDuration duration,
8081
const std::optional<DevToolsTrackEntryPayload>& trackMetadata);
8182

8283
/**
@@ -99,13 +100,13 @@ class PerformanceTracer {
99100
* Record an Event Loop tick, which will be represented as an Event Loop task
100101
* on a timeline view and grouped with JavaScript samples.
101102
*/
102-
void reportEventLoopTask(uint64_t start, uint64_t end);
103+
void reportEventLoopTask(HighResTimeStamp start, HighResTimeStamp end);
103104

104105
/**
105106
* Record Microtasks phase of the Event Loop tick. Will be represented as a
106107
* "Run Microtasks" block under a task.
107108
*/
108-
void reportEventLoopMicrotasks(uint64_t start, uint64_t end);
109+
void reportEventLoopMicrotasks(HighResTimeStamp start, HighResTimeStamp end);
109110

110111
/**
111112
* Create and serialize Profile Trace Event.
@@ -114,7 +115,7 @@ class PerformanceTracer {
114115
folly::dynamic getSerializedRuntimeProfileTraceEvent(
115116
uint64_t threadId,
116117
uint16_t profileId,
117-
uint64_t eventUnixTimestamp);
118+
HighResTimeStamp profileTimestamp);
118119

119120
/**
120121
* Create and serialize ProfileChunk Trace Event.
@@ -123,8 +124,8 @@ class PerformanceTracer {
123124
folly::dynamic getSerializedRuntimeProfileChunkTraceEvent(
124125
uint16_t profileId,
125126
uint64_t threadId,
126-
uint64_t eventUnixTimestamp,
127-
const tracing::TraceEventProfileChunk& traceEventProfileChunk);
127+
HighResTimeStamp chunkTimestamp,
128+
const TraceEventProfileChunk& traceEventProfileChunk);
128129

129130
private:
130131
PerformanceTracer();
@@ -135,10 +136,11 @@ class PerformanceTracer {
135136
folly::dynamic serializeTraceEvent(const TraceEvent& event) const;
136137

137138
bool tracing_{false};
139+
138140
uint64_t processId_;
139141
uint32_t performanceMeasureCount_{0};
140142
std::vector<TraceEvent> buffer_;
141143
std::mutex mutex_;
142144
};
143145

144-
} // namespace facebook::react::jsinspector_modern
146+
} // namespace facebook::react::jsinspector_modern::tracing

packages/react-native/ReactCommon/jsinspector-modern/tracing/React-jsinspectortracing.podspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Pod::Spec.new do |s|
4747
end
4848

4949
s.dependency "React-oscompat"
50+
s.dependency "React-timing"
5051

5152
add_rn_third_party_dependencies(s)
5253
end

0 commit comments

Comments
 (0)