Avoid copying strings when serializing TraceEvent / lock only on buffer operations (#52220)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52220

# Changelog: [Internal]

Mainly, 2 changes:
1. `PerformanceTracer::serializeTraceEvent(const TraceEvent& event)` -> `PerformanceTracer::serializeTraceEvent(TraceEvent&& event)` for less copies, actually move strings from the `TraceEvent` into the serialized `folly:object`.
2. When collecting events from the buffer, only lock when accessing buffer, not when serializing.

Reviewed By: rubennorte

Differential Revision: D77164969

fbshipit-source-id: c7dd84dd3c94dae22b89ffd4b229974e6d8084de
This commit is contained in:
Ruslan Lesiutin
2025-06-25 05:38:31 -07:00
committed by Facebook GitHub Bot
parent 448fe573e0
commit ca647c13c2
2 changed files with 25 additions and 17 deletions
@@ -87,27 +87,29 @@ void PerformanceTracer::collectEvents(
const std::function<void(const folly::dynamic& eventsChunk)>&
resultCallback,
uint16_t chunkSize) {
std::lock_guard lock(tracingMutex_);
std::vector<TraceEvent> localBuffer;
{
std::lock_guard lock(tracingMutex_);
buffer_.swap(localBuffer);
}
if (buffer_.empty()) {
if (localBuffer.empty()) {
return;
}
auto traceEvents = folly::dynamic::array();
for (const auto& event : buffer_) {
auto serializedTraceEvents = folly::dynamic::array();
for (auto&& event : localBuffer) {
// Emit trace events
traceEvents.push_back(serializeTraceEvent(event));
serializedTraceEvents.push_back(serializeTraceEvent(std::move(event)));
if (traceEvents.size() == chunkSize) {
resultCallback(traceEvents);
traceEvents = folly::dynamic::array();
if (serializedTraceEvents.size() == chunkSize) {
resultCallback(serializedTraceEvents);
serializedTraceEvents = folly::dynamic::array();
}
}
if (!traceEvents.empty()) {
resultCallback(traceEvents);
if (!serializedTraceEvents.empty()) {
resultCallback(serializedTraceEvents);
}
buffer_.clear();
}
void PerformanceTracer::reportMark(
@@ -326,7 +328,7 @@ folly::dynamic PerformanceTracer::getSerializedRuntimeProfileChunkTraceEvent(
}
folly::dynamic PerformanceTracer::serializeTraceEvent(
const TraceEvent& event) const {
TraceEvent&& event) const {
folly::dynamic result = folly::dynamic::object;
if (event.id.has_value()) {
@@ -334,13 +336,13 @@ folly::dynamic PerformanceTracer::serializeTraceEvent(
snprintf(buffer.data(), buffer.size(), "0x%x", event.id.value());
result["id"] = buffer.data();
}
result["name"] = event.name;
result["cat"] = event.cat;
result["name"] = std::move(event.name);
result["cat"] = std::move(event.cat);
result["ph"] = std::string(1, event.ph);
result["ts"] = highResTimeStampToTracingClockTimeStamp(event.ts);
result["pid"] = event.pid;
result["tid"] = event.tid;
result["args"] = event.args;
result["args"] = std::move(event.args);
if (event.dur.has_value()) {
result["dur"] = highResDurationToTracingClockDuration(event.dur.value());
}
@@ -132,7 +132,13 @@ class PerformanceTracer {
PerformanceTracer& operator=(const PerformanceTracer&) = delete;
~PerformanceTracer() = default;
folly::dynamic serializeTraceEvent(const TraceEvent& event) const;
/**
* Serialize a TraceEvent into a folly::dynamic object.
* \param event rvalue reference to the TraceEvent object.
* \return folly::dynamic object that represents a serialized into JSON Trace
* Event for CDP.
*/
folly::dynamic serializeTraceEvent(TraceEvent&& event) const;
uint64_t processId_;