mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Avoid copies when dispatching TraceEvent chunks (#52868)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/52868 # Changelog: [Internal] Mainly, 2 changes: - Callback that emits `Tracing.dataCollected` events will receive chunks as rvalues refs (`&&`), instead of `const &`. - The RuntimeSamplingProfile will be passed to the serializer as rvalue ref. Reviewed By: huntie Differential Revision: D78919223 fbshipit-source-id: 7f65e0627c8839d507e6b2d088fdb0b560906b6a
This commit is contained in:
committed by
Facebook GitHub Bot
parent
3cf11a3113
commit
75d6cb1138
@@ -102,10 +102,10 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
|
||||
// Send response to Tracing.end request.
|
||||
frontendChannel_(cdp::jsonResult(req.id));
|
||||
|
||||
auto dataCollectedCallback = [this](const folly::dynamic& eventsChunk) {
|
||||
auto dataCollectedCallback = [this](folly::dynamic&& eventsChunk) {
|
||||
frontendChannel_(cdp::jsonNotification(
|
||||
"Tracing.dataCollected",
|
||||
folly::dynamic::object("value", eventsChunk)));
|
||||
folly::dynamic::object("value", std::move(eventsChunk))));
|
||||
};
|
||||
performanceTracer.collectEvents(
|
||||
dataCollectedCallback, TRACE_EVENT_CHUNK_SIZE);
|
||||
@@ -114,8 +114,9 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
|
||||
performanceTracer,
|
||||
dataCollectedCallback,
|
||||
PROFILE_TRACE_EVENT_CHUNK_SIZE);
|
||||
auto tracingProfile = instanceAgent_->collectTracingProfile();
|
||||
serializer.serializeAndNotify(
|
||||
instanceAgent_->collectTracingProfile().runtimeSamplingProfile,
|
||||
std::move(tracingProfile.runtimeSamplingProfile),
|
||||
instanceTracingStartTimestamp_);
|
||||
|
||||
frontendChannel_(cdp::jsonNotification(
|
||||
|
||||
@@ -83,8 +83,7 @@ bool PerformanceTracer::stopTracing() {
|
||||
}
|
||||
|
||||
void PerformanceTracer::collectEvents(
|
||||
const std::function<void(const folly::dynamic& eventsChunk)>&
|
||||
resultCallback,
|
||||
const std::function<void(folly::dynamic&& eventsChunk)>& resultCallback,
|
||||
uint16_t chunkSize) {
|
||||
std::vector<TraceEvent> localBuffer;
|
||||
{
|
||||
@@ -102,12 +101,12 @@ void PerformanceTracer::collectEvents(
|
||||
serializedTraceEvents.push_back(serializeTraceEvent(std::move(event)));
|
||||
|
||||
if (serializedTraceEvents.size() == chunkSize) {
|
||||
resultCallback(serializedTraceEvents);
|
||||
resultCallback(std::move(serializedTraceEvents));
|
||||
serializedTraceEvents = folly::dynamic::array();
|
||||
}
|
||||
}
|
||||
if (!serializedTraceEvents.empty()) {
|
||||
resultCallback(serializedTraceEvents);
|
||||
resultCallback(std::move(serializedTraceEvents));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,8 +56,7 @@ class PerformanceTracer {
|
||||
* Flush out buffered CDP Trace Events using the given callback.
|
||||
*/
|
||||
void collectEvents(
|
||||
const std::function<void(const folly::dynamic& eventsChunk)>&
|
||||
resultCallback,
|
||||
const std::function<void(folly::dynamic&& eventsChunk)>& resultCallback,
|
||||
uint16_t chunkSize);
|
||||
|
||||
/**
|
||||
|
||||
+16
-11
@@ -115,7 +115,7 @@ void RuntimeSamplingProfileTraceEventSerializer::chunkEmptySample(
|
||||
}
|
||||
|
||||
void RuntimeSamplingProfileTraceEventSerializer::bufferProfileChunkTraceEvent(
|
||||
ProfileChunk& chunk,
|
||||
ProfileChunk&& chunk,
|
||||
uint16_t profileId) {
|
||||
if (chunk.isEmpty()) {
|
||||
return;
|
||||
@@ -135,14 +135,17 @@ void RuntimeSamplingProfileTraceEventSerializer::bufferProfileChunkTraceEvent(
|
||||
TraceEventProfileChunk{
|
||||
.cpuProfile =
|
||||
TraceEventProfileChunk::CPUProfile{
|
||||
traceEventNodes, chunk.samples},
|
||||
.nodes = std::move(traceEventNodes),
|
||||
.samples = std::move(chunk.samples)},
|
||||
.timeDeltas =
|
||||
TraceEventProfileChunk::TimeDeltas{chunk.timeDeltas},
|
||||
TraceEventProfileChunk::TimeDeltas{
|
||||
.deltas = std::move(chunk.timeDeltas),
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
void RuntimeSamplingProfileTraceEventSerializer::processCallStack(
|
||||
const std::vector<RuntimeSamplingProfile::SampleCallStackFrame>& callStack,
|
||||
std::vector<RuntimeSamplingProfile::SampleCallStackFrame>&& callStack,
|
||||
ProfileChunk& chunk,
|
||||
ProfileTreeNode& rootNode,
|
||||
uint32_t idleNodeId,
|
||||
@@ -184,14 +187,16 @@ void RuntimeSamplingProfileTraceEventSerializer::processCallStack(
|
||||
|
||||
void RuntimeSamplingProfileTraceEventSerializer::
|
||||
sendBufferedTraceEventsAndClear() {
|
||||
notificationCallback_(traceEventBuffer_);
|
||||
notificationCallback_(std::move(traceEventBuffer_));
|
||||
|
||||
traceEventBuffer_ = folly::dynamic::array();
|
||||
traceEventBuffer_.reserve(traceEventChunkSize_);
|
||||
}
|
||||
|
||||
void RuntimeSamplingProfileTraceEventSerializer::serializeAndNotify(
|
||||
const RuntimeSamplingProfile& profile,
|
||||
RuntimeSamplingProfile&& profile,
|
||||
HighResTimeStamp tracingStartTime) {
|
||||
const std::vector<RuntimeSamplingProfile::Sample>& samples = profile.samples;
|
||||
auto samples = std::move(profile.samples);
|
||||
if (samples.empty()) {
|
||||
return;
|
||||
}
|
||||
@@ -225,7 +230,7 @@ void RuntimeSamplingProfileTraceEventSerializer::serializeAndNotify(
|
||||
chunk.nodes.push_back(*idleNode);
|
||||
uint32_t idleNodeId = idleNode->getId();
|
||||
|
||||
for (const auto& sample : samples) {
|
||||
for (auto& sample : samples) {
|
||||
uint64_t currentSampleThreadId = sample.threadId;
|
||||
auto currentSampleTimestamp = getHighResTimeStampForSample(sample);
|
||||
|
||||
@@ -234,7 +239,7 @@ void RuntimeSamplingProfileTraceEventSerializer::serializeAndNotify(
|
||||
// We should group samples by thread id once we support executing JavaScript
|
||||
// on different threads.
|
||||
if (currentSampleThreadId != chunk.threadId || chunk.isFull()) {
|
||||
bufferProfileChunkTraceEvent(chunk, PROFILE_ID);
|
||||
bufferProfileChunkTraceEvent(std::move(chunk), PROFILE_ID);
|
||||
chunk = ProfileChunk{
|
||||
profileChunkSize_, currentSampleThreadId, currentChunkTimestamp};
|
||||
}
|
||||
@@ -244,7 +249,7 @@ void RuntimeSamplingProfileTraceEventSerializer::serializeAndNotify(
|
||||
}
|
||||
|
||||
processCallStack(
|
||||
sample.callStack,
|
||||
std::move(sample.callStack),
|
||||
chunk,
|
||||
rootNode,
|
||||
idleNodeId,
|
||||
@@ -255,7 +260,7 @@ void RuntimeSamplingProfileTraceEventSerializer::serializeAndNotify(
|
||||
}
|
||||
|
||||
if (!chunk.isEmpty()) {
|
||||
bufferProfileChunkTraceEvent(chunk, PROFILE_ID);
|
||||
bufferProfileChunkTraceEvent(std::move(chunk), PROFILE_ID);
|
||||
}
|
||||
|
||||
if (!traceEventBuffer_.empty()) {
|
||||
|
||||
+7
-8
@@ -72,7 +72,7 @@ class RuntimeSamplingProfileTraceEventSerializer {
|
||||
*/
|
||||
RuntimeSamplingProfileTraceEventSerializer(
|
||||
PerformanceTracer& performanceTracer,
|
||||
std::function<void(const folly::dynamic& traceEventsChunk)>
|
||||
std::function<void(folly::dynamic&& traceEventsChunk)>
|
||||
notificationCallback,
|
||||
uint16_t traceEventChunkSize,
|
||||
uint16_t profileChunkSize = 10)
|
||||
@@ -90,7 +90,7 @@ class RuntimeSamplingProfileTraceEventSerializer {
|
||||
* will be used as a starting reference point of JavaScript samples recording.
|
||||
*/
|
||||
void serializeAndNotify(
|
||||
const RuntimeSamplingProfile& profile,
|
||||
RuntimeSamplingProfile&& profile,
|
||||
HighResTimeStamp tracingStartTime);
|
||||
|
||||
private:
|
||||
@@ -123,7 +123,7 @@ class RuntimeSamplingProfileTraceEventSerializer {
|
||||
* \param chunk The chunk that will be buffered.
|
||||
* \param profileId The id of the Profile.
|
||||
*/
|
||||
void bufferProfileChunkTraceEvent(ProfileChunk& chunk, uint16_t profileId);
|
||||
void bufferProfileChunkTraceEvent(ProfileChunk&& chunk, uint16_t profileId);
|
||||
|
||||
/**
|
||||
* Encapsulates logic for processing the call stack of the sample.
|
||||
@@ -140,8 +140,7 @@ class RuntimeSamplingProfileTraceEventSerializer {
|
||||
* generating unique node ids.
|
||||
*/
|
||||
void processCallStack(
|
||||
const std::vector<RuntimeSamplingProfile::SampleCallStackFrame>&
|
||||
callStack,
|
||||
std::vector<RuntimeSamplingProfile::SampleCallStackFrame>&& callStack,
|
||||
ProfileChunk& chunk,
|
||||
ProfileTreeNode& rootNode,
|
||||
uint32_t idleNodeId,
|
||||
@@ -154,10 +153,10 @@ class RuntimeSamplingProfileTraceEventSerializer {
|
||||
void sendBufferedTraceEventsAndClear();
|
||||
|
||||
PerformanceTracer& performanceTracer_;
|
||||
const std::function<void(const folly::dynamic& traceEventsChunk)>
|
||||
const std::function<void(folly::dynamic&& traceEventsChunk)>
|
||||
notificationCallback_;
|
||||
uint16_t traceEventChunkSize_;
|
||||
uint16_t profileChunkSize_;
|
||||
const uint16_t traceEventChunkSize_;
|
||||
const uint16_t profileChunkSize_;
|
||||
|
||||
folly::dynamic traceEventBuffer_;
|
||||
};
|
||||
|
||||
+8
-8
@@ -18,9 +18,9 @@ class RuntimeSamplingProfileTraceEventSerializerTest : public ::testing::Test {
|
||||
protected:
|
||||
std::vector<folly::dynamic> notificationEvents_;
|
||||
|
||||
std::function<void(const folly::dynamic& traceEventsChunk)>
|
||||
std::function<void(folly::dynamic&& traceEventsChunk)>
|
||||
createNotificationCallback() {
|
||||
return [this](const folly::dynamic& traceEventsChunk) {
|
||||
return [this](folly::dynamic&& traceEventsChunk) {
|
||||
notificationEvents_.push_back(traceEventsChunk);
|
||||
};
|
||||
}
|
||||
@@ -74,7 +74,7 @@ TEST_F(RuntimeSamplingProfileTraceEventSerializerTest, EmptyProfile) {
|
||||
auto tracingStartTime = HighResTimeStamp::now();
|
||||
|
||||
// Execute
|
||||
serializer.serializeAndNotify(profile, tracingStartTime);
|
||||
serializer.serializeAndNotify(std::move(profile), tracingStartTime);
|
||||
|
||||
// Nothing should be reported if the profile is empty.
|
||||
EXPECT_TRUE(notificationEvents_.empty());
|
||||
@@ -122,7 +122,7 @@ TEST_F(
|
||||
auto tracingStartTime = HighResTimeStamp::now();
|
||||
|
||||
// Execute
|
||||
serializer.serializeAndNotify(profile, tracingStartTime);
|
||||
serializer.serializeAndNotify(std::move(profile), tracingStartTime);
|
||||
|
||||
// Verify
|
||||
ASSERT_EQ(notificationEvents_.size(), 2);
|
||||
@@ -155,7 +155,7 @@ TEST_F(RuntimeSamplingProfileTraceEventSerializerTest, EmptySample) {
|
||||
folly::dynamic chunkEvent = folly::dynamic::object;
|
||||
|
||||
// Execute
|
||||
serializer.serializeAndNotify(profile, tracingStartTime);
|
||||
serializer.serializeAndNotify(std::move(profile), tracingStartTime);
|
||||
|
||||
// Verify
|
||||
// [["Profile"], ["ProfileChunk"]]
|
||||
@@ -192,7 +192,7 @@ TEST_F(
|
||||
auto tracingStartTime = HighResTimeStamp::now();
|
||||
|
||||
// Execute
|
||||
serializer.serializeAndNotify(profile, tracingStartTime);
|
||||
serializer.serializeAndNotify(std::move(profile), tracingStartTime);
|
||||
|
||||
// [["Profile"], ["ProfileChunk", "ProfileChunk", "ProfileChunk]]
|
||||
// Samples from different thread should never be grouped together in the same
|
||||
@@ -231,7 +231,7 @@ TEST_F(
|
||||
auto tracingStartTime = HighResTimeStamp::now();
|
||||
|
||||
// Execute
|
||||
serializer.serializeAndNotify(profile, tracingStartTime);
|
||||
serializer.serializeAndNotify(std::move(profile), tracingStartTime);
|
||||
|
||||
// [["Profile"], ["ProfileChunk", "ProfileChunk"], ["ProfileChunk"]]
|
||||
ASSERT_EQ(notificationEvents_.size(), 3);
|
||||
@@ -272,7 +272,7 @@ TEST_F(RuntimeSamplingProfileTraceEventSerializerTest, ProfileChunkSizeLimit) {
|
||||
auto tracingStartTime = HighResTimeStamp::now();
|
||||
|
||||
// Execute
|
||||
serializer.serializeAndNotify(profile, tracingStartTime);
|
||||
serializer.serializeAndNotify(std::move(profile), tracingStartTime);
|
||||
|
||||
// [["Profile"], ["ProfileChunk", "ProfileChunk", "ProfileChunk"]]
|
||||
ASSERT_EQ(notificationEvents_.size(), 2);
|
||||
|
||||
Reference in New Issue
Block a user