From ca647c13c22f60ef302ffdbf460d298f1367f3c5 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Wed, 25 Jun 2025 05:38:31 -0700 Subject: [PATCH] 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 --- .../tracing/PerformanceTracer.cpp | 34 ++++++++++--------- .../tracing/PerformanceTracer.h | 8 ++++- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp index 07dd7b2624f..3112d0e7f70 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp @@ -87,27 +87,29 @@ void PerformanceTracer::collectEvents( const std::function& resultCallback, uint16_t chunkSize) { - std::lock_guard lock(tracingMutex_); + std::vector 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()); } diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.h b/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.h index 890b9b1f140..5cacb3971af 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.h @@ -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_;