Skip to content

Commit 9f6440d

Browse files
rubennortefacebook-github-bot
authored andcommitted
Simplify PerformanceTracer API and move processing to TracingAgent (#52934)
Summary: Pull Request resolved: #52934 Changelog: [internal] Right now, the `PerformanceTracer` API has a method to stop the trace and a separate one to collect serialized events. This refactors the API to return the collected events when calling `stopTracing` instead. The caller (in this case `TracingAgent`) is responsible for serializing and sending the events in chunks through CDP. Reviewed By: hoxyq Differential Revision: D79271690 fbshipit-source-id: bdb48c80be4fd07d96e381e6bb4d099cae91f8de
1 parent f718571 commit 9f6440d

3 files changed

Lines changed: 50 additions & 77 deletions

File tree

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

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <jsinspector-modern/tracing/PerformanceTracer.h>
1111
#include <jsinspector-modern/tracing/RuntimeSamplingProfileTraceEventSerializer.h>
12+
#include <jsinspector-modern/tracing/TraceEventSerializer.h>
1213

1314
namespace facebook::react::jsinspector_modern {
1415

@@ -29,6 +30,26 @@ const uint16_t TRACE_EVENT_CHUNK_SIZE = 1000;
2930
*/
3031
const uint16_t PROFILE_TRACE_EVENT_CHUNK_SIZE = 1;
3132

33+
void serializeTraceEventsInChunks(
34+
std::vector<tracing::TraceEvent>&& traceEvents,
35+
uint16_t chunkSize,
36+
const std::function<void(folly::dynamic&& eventsChunk)>& resultCallback) {
37+
auto serializedTraceEvents = folly::dynamic::array();
38+
for (auto&& traceEvent : traceEvents) {
39+
// Emit trace events
40+
serializedTraceEvents.push_back(
41+
tracing::TraceEventSerializer::serialize(std::move(traceEvent)));
42+
43+
if (serializedTraceEvents.size() == chunkSize) {
44+
resultCallback(std::move(serializedTraceEvents));
45+
serializedTraceEvents = folly::dynamic::array();
46+
}
47+
}
48+
if (!serializedTraceEvents.empty()) {
49+
resultCallback(std::move(serializedTraceEvents));
50+
}
51+
}
52+
3253
} // namespace
3354

3455
TracingAgent::TracingAgent(
@@ -89,8 +110,8 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
89110

90111
tracing::PerformanceTracer& performanceTracer =
91112
tracing::PerformanceTracer::getInstance();
92-
bool correctlyStopped = performanceTracer.stopTracing();
93-
if (!correctlyStopped) {
113+
auto collectedEvents = performanceTracer.stopTracing();
114+
if (!collectedEvents) {
94115
frontendChannel_(cdp::jsonError(
95116
req.id,
96117
cdp::ErrorCode::InternalError,
@@ -107,8 +128,11 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
107128
"Tracing.dataCollected",
108129
folly::dynamic::object("value", std::move(eventsChunk))));
109130
};
110-
performanceTracer.collectEvents(
111-
dataCollectedCallback, TRACE_EVENT_CHUNK_SIZE);
131+
132+
serializeTraceEventsInChunks(
133+
std::move(*collectedEvents),
134+
TRACE_EVENT_CHUNK_SIZE,
135+
dataCollectedCallback);
112136

113137
auto tracingProfile = instanceAgent_->collectTracingProfile();
114138
tracing::IdGenerator profileIdGenerator;

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

Lines changed: 18 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -28,38 +28,39 @@ PerformanceTracer::PerformanceTracer()
2828

2929
bool PerformanceTracer::startTracing() {
3030
std::lock_guard lock(mutex_);
31+
3132
if (tracingAtomic_) {
3233
return false;
3334
}
34-
tracingAtomic_ = true;
3535

36-
buffer_.emplace_back(TraceEvent{
37-
.name = "TracingStartedInPage",
38-
.cat = "disabled-by-default-devtools.timeline",
39-
.ph = 'I',
40-
.ts = HighResTimeStamp::now(),
41-
.pid = processId_,
42-
.tid = oscompat::getCurrentThreadId(),
43-
.args = folly::dynamic::object("data", folly::dynamic::object()),
44-
});
36+
tracingAtomic_ = true;
4537

4638
return true;
4739
}
4840

49-
bool PerformanceTracer::stopTracing() {
50-
std::lock_guard lock(mutex_);
51-
if (!tracingAtomic_) {
52-
return false;
41+
std::optional<std::vector<TraceEvent>> PerformanceTracer::stopTracing() {
42+
std::vector<TraceEvent> events;
43+
44+
{
45+
std::lock_guard lock(mutex_);
46+
47+
if (!tracingAtomic_) {
48+
return std::nullopt;
49+
}
50+
51+
tracingAtomic_ = false;
52+
performanceMeasureCount_ = 0;
53+
54+
buffer_.swap(events);
5355
}
54-
tracingAtomic_ = false;
5556

5657
// This is synthetic Trace Event, which should not be represented on a
5758
// timeline. CDT is not using Profile or ProfileChunk events for determining
5859
// trace timeline window, this is why trace that only contains JavaScript
59-
// samples will be displayed as empty. We use this event to avoid that.
60+
// samples will be displayed as empty. We use these events to avoid that.
6061
// This could happen for non-bridgeless apps, where Performance interface is
6162
// not supported and no spec-compliant Event Loop implementation.
62-
buffer_.emplace_back(TraceEvent{
63+
events.emplace_back(TraceEvent{
6364
.name = "ReactNative-TracingStopped",
6465
.cat = "disabled-by-default-devtools.timeline",
6566
.ph = 'I',
@@ -68,45 +69,6 @@ bool PerformanceTracer::stopTracing() {
6869
.tid = oscompat::getCurrentThreadId(),
6970
});
7071

71-
performanceMeasureCount_ = 0;
72-
return true;
73-
}
74-
75-
void PerformanceTracer::collectEvents(
76-
const std::function<void(folly::dynamic&& eventsChunk)>& resultCallback,
77-
uint16_t chunkSize) {
78-
std::vector<TraceEvent> localBuffer;
79-
{
80-
std::lock_guard lock(mutex_);
81-
buffer_.swap(localBuffer);
82-
}
83-
84-
if (localBuffer.empty()) {
85-
return;
86-
}
87-
88-
auto serializedTraceEvents = folly::dynamic::array();
89-
for (auto&& event : localBuffer) {
90-
// Emit trace events
91-
serializedTraceEvents.push_back(
92-
TraceEventSerializer::serialize(std::move(event)));
93-
94-
if (serializedTraceEvents.size() == chunkSize) {
95-
resultCallback(std::move(serializedTraceEvents));
96-
serializedTraceEvents = folly::dynamic::array();
97-
}
98-
}
99-
if (!serializedTraceEvents.empty()) {
100-
resultCallback(std::move(serializedTraceEvents));
101-
}
102-
}
103-
104-
std::vector<TraceEvent> PerformanceTracer::collectTraceEvents() {
105-
std::vector<TraceEvent> events;
106-
{
107-
std::lock_guard lock(mutex_);
108-
buffer_.swap(events);
109-
}
11072
return events;
11173
}
11274

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

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
#include <folly/dynamic.h>
1717
#include <atomic>
18-
#include <functional>
1918
#include <mutex>
2019
#include <optional>
2120
#include <vector>
@@ -34,14 +33,15 @@ class PerformanceTracer {
3433
static PerformanceTracer& getInstance();
3534

3635
/**
37-
* Mark trace session as started. Returns `false` if already tracing.
36+
* Starts a tracing session. Returns `false` if already tracing.
3837
*/
3938
bool startTracing();
4039

4140
/**
42-
* Mark trace session as stopped. Returns `false` if wasn't tracing.
41+
* If there is a current tracing session, it stops tracing and returns all
42+
* collected events. Otherwise, it returns empty.
4343
*/
44-
bool stopTracing();
44+
std::optional<std::vector<TraceEvent>> stopTracing();
4545

4646
/**
4747
* Returns whether the tracer is currently tracing. This can be useful to
@@ -52,19 +52,6 @@ class PerformanceTracer {
5252
return tracingAtomic_;
5353
}
5454

55-
/**
56-
* Flush out buffered CDP Trace Events using the given callback.
57-
*/
58-
void collectEvents(
59-
const std::function<void(folly::dynamic&& eventsChunk)>& resultCallback,
60-
uint16_t chunkSize);
61-
62-
/**
63-
* Transfers an ownership of all buffered TraceEvents, the local buffer state
64-
* is invalidated after this call.
65-
*/
66-
std::vector<TraceEvent> collectTraceEvents();
67-
6855
/**
6956
* Record a `Performance.mark()` event - a labelled timestamp. If not
7057
* currently tracing, this is a no-op.

0 commit comments

Comments
 (0)