Skip to content

Commit ef1f862

Browse files
rubennortefacebook-github-bot
authored andcommitted
Add tracing helper functions for RNDT traces in C++ and Kotlin (facebook#55935)
Summary: Changelog: [internal] This diff adds helper functions to the PerformanceTracer class for tracing performance events in React Native Developer Tools traces. In Kotlin, new `trace` method overloads are added to `PerformanceTracer` that wrap a block of code and automatically measure and report its execution time. These use a try/finally pattern to ensure timing is captured correctly. In C++, a new `PerformanceTracerSection` RAII class is added that automatically reports timing when the section goes out of scope. It supports optional track, track group, and color parameters, as well as variadic key-value properties for additional metadata. Reviewed By: sammy-SC Differential Revision: D92061513
1 parent 57e42c2 commit ef1f862

File tree

2 files changed

+152
-0
lines changed

2 files changed

+152
-0
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/tracing/PerformanceTracer.kt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,45 @@ public object PerformanceTracer {
2323
SoLoader.loadLibrary("react_performancetracerjni")
2424
}
2525

26+
public fun <T> trace(name: String, block: () -> T): T {
27+
return trace(name, null /* track */, null /* trackGroup */, null /* color */, block)
28+
}
29+
30+
public fun <T> trace(name: String, track: String, block: () -> T): T {
31+
return trace(name, track, null /* trackGroup */, null /* color */, block)
32+
}
33+
34+
public fun <T> trace(name: String, track: String, trackGroup: String, block: () -> T): T {
35+
return trace(name, track, trackGroup, null /* color */, block)
36+
}
37+
38+
public fun <T> trace(
39+
name: String,
40+
track: String?,
41+
trackGroup: String?,
42+
color: String?,
43+
block: () -> T,
44+
): T {
45+
if (!isTracing()) {
46+
return block()
47+
}
48+
49+
val startTimeNanos = java.lang.System.nanoTime()
50+
try {
51+
return block()
52+
} finally {
53+
val endTimeNanos = java.lang.System.nanoTime()
54+
reportTimeStamp(
55+
name,
56+
startTimeNanos,
57+
endTimeNanos,
58+
track,
59+
trackGroup,
60+
color,
61+
)
62+
}
63+
}
64+
2665
/** Callback interface for tracing state changes. */
2766
@DoNotStrip
2867
public interface TracingStateCallback {
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <folly/dynamic.h>
11+
12+
#include <jsinspector-modern/tracing/PerformanceTracer.h>
13+
14+
#include <string_view>
15+
16+
namespace facebook::react::jsinspector_modern::tracing {
17+
18+
/**
19+
* This is a RAII class that reports a timeStamp block to the React Native
20+
* Performance Tracer.
21+
*
22+
* @example
23+
* {
24+
* PerformanceTracerSection s("name", "track", "track group");
25+
* // do something
26+
* }
27+
*/
28+
template <typename... Args>
29+
class PerformanceTracerSection {
30+
public:
31+
explicit PerformanceTracerSection(
32+
const char *name,
33+
const char *track = nullptr,
34+
const char *trackGroup = nullptr,
35+
const char *color = nullptr,
36+
Args... args) noexcept
37+
: name_(name), track_(track), trackGroup_(trackGroup), color_(color), args_(std::move(args)...)
38+
{
39+
static_assert(
40+
sizeof...(Args) % 2 == 0,
41+
"PerformanceTracerSection expects an even number of variadic args representing [name, value] pairs.");
42+
}
43+
44+
// Non-movable
45+
PerformanceTracerSection(const PerformanceTracerSection &) = delete;
46+
PerformanceTracerSection(PerformanceTracerSection &&) = delete;
47+
48+
// Non-copyable
49+
PerformanceTracerSection &operator=(const PerformanceTracerSection &) = delete;
50+
PerformanceTracerSection &operator=(PerformanceTracerSection &&) = delete;
51+
52+
~PerformanceTracerSection() noexcept
53+
{
54+
auto &tracer = PerformanceTracer::getInstance();
55+
if (!tracer.isTracing()) {
56+
return;
57+
}
58+
59+
auto endTime = HighResTimeStamp::now();
60+
61+
// Slow path when passing properties
62+
if constexpr (sizeof...(Args) > 0) {
63+
auto properties = folly::dynamic::array();
64+
std::apply(
65+
[&](const auto &...elems) {
66+
size_t idx = 0;
67+
(((idx % 2 == 0) ? properties.push_back(folly::dynamic::array(elems))
68+
: properties[properties.size() - 1].push_back(elems),
69+
++idx),
70+
...);
71+
},
72+
args_);
73+
74+
folly::dynamic devtools = folly::dynamic::object();
75+
devtools["properties"] = std::move(properties);
76+
77+
if (track_ != nullptr) {
78+
devtools["track"] = track_;
79+
}
80+
81+
if (trackGroup_ != nullptr) {
82+
devtools["trackGroup"] = trackGroup_;
83+
}
84+
85+
if (color_ != nullptr) {
86+
devtools["color"] = color_;
87+
}
88+
89+
folly::dynamic detail = folly::dynamic::object();
90+
detail["devtools"] = std::move(devtools);
91+
92+
tracer.reportMeasure(std::string(name_), startTime_, endTime - startTime_, std::move(detail));
93+
} else {
94+
tracer.reportTimeStamp(
95+
std::string(name_),
96+
startTime_,
97+
endTime,
98+
track_ != nullptr ? std::optional{track_} : std::nullopt,
99+
trackGroup_ != nullptr ? std::optional{trackGroup_} : std::nullopt,
100+
color_ != nullptr ? getConsoleTimeStampColorFromString(color_) : std::nullopt);
101+
}
102+
}
103+
104+
private:
105+
HighResTimeStamp startTime_{HighResTimeStamp::now()};
106+
std::string_view name_;
107+
const char *track_;
108+
const char *trackGroup_;
109+
const char *color_;
110+
std::tuple<Args...> args_;
111+
};
112+
113+
} // namespace facebook::react::jsinspector_modern::tracing

0 commit comments

Comments
 (0)