Skip to content

Commit aa0138e

Browse files
huntiefacebook-github-bot
authored andcommitted
Refactor PerformanceEntry as std::variant (#50995)
Summary: Pull Request resolved: #50995 Refactors our previous single-struct representation for `PerformanceEntry` ([see MDN](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry)) as a `std::variant`. This maps closely to the `PerformanceEntry` type inheritance in the web spec, and makes this type substantially cleaner to extend and work with in D73861431. Changelog: [Internal] Reviewed By: rshest Differential Revision: D73860532
1 parent 81f3f09 commit aa0138e

File tree

14 files changed

+285
-314
lines changed

14 files changed

+285
-314
lines changed

packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
#include "NativePerformance.h"
99

1010
#include <memory>
11-
#include <mutex>
1211
#include <unordered_map>
12+
#include <variant>
1313

1414
#include <cxxreact/JSExecutor.h>
1515
#include <cxxreact/ReactMarker.h>
@@ -47,6 +47,40 @@ void sortEntries(std::vector<PerformanceEntry>& entries) {
4747
entries.begin(), entries.end(), PerformanceEntrySorter{});
4848
}
4949

50+
NativePerformanceEntry toNativePerformanceEntry(const PerformanceEntry& entry) {
51+
auto nativeEntry = std::visit(
52+
[](const auto& entryData) -> NativePerformanceEntry {
53+
return {
54+
.name = entryData.name,
55+
.entryType = entryData.entryType,
56+
.startTime = entryData.startTime,
57+
.duration = entryData.duration,
58+
};
59+
},
60+
entry);
61+
62+
if (std::holds_alternative<PerformanceEventTiming>(entry)) {
63+
auto eventEntry = std::get<PerformanceEventTiming>(entry);
64+
nativeEntry.processingStart = eventEntry.processingStart;
65+
nativeEntry.processingEnd = eventEntry.processingEnd;
66+
nativeEntry.interactionId = eventEntry.interactionId;
67+
}
68+
69+
return nativeEntry;
70+
}
71+
72+
std::vector<NativePerformanceEntry> toNativePerformanceEntries(
73+
std::vector<PerformanceEntry>& entries) {
74+
std::vector<NativePerformanceEntry> result;
75+
result.reserve(entries.size());
76+
77+
for (auto& entry : entries) {
78+
result.emplace_back(toNativePerformanceEntry(entry));
79+
}
80+
81+
return result;
82+
}
83+
5084
const std::array<PerformanceEntryType, 2> ENTRY_TYPES_AVAILABLE_FROM_TIMELINE{
5185
{PerformanceEntryType::MARK, PerformanceEntryType::MEASURE}};
5286

@@ -122,7 +156,7 @@ void NativePerformance::clearMeasures(
122156
}
123157
}
124158

125-
std::vector<PerformanceEntry> NativePerformance::getEntries(
159+
std::vector<NativePerformanceEntry> NativePerformance::getEntries(
126160
jsi::Runtime& /*rt*/) {
127161
std::vector<PerformanceEntry> entries;
128162

@@ -132,10 +166,10 @@ std::vector<PerformanceEntry> NativePerformance::getEntries(
132166

133167
sortEntries(entries);
134168

135-
return entries;
169+
return toNativePerformanceEntries(entries);
136170
}
137171

138-
std::vector<PerformanceEntry> NativePerformance::getEntriesByName(
172+
std::vector<NativePerformanceEntry> NativePerformance::getEntriesByName(
139173
jsi::Runtime& /*rt*/,
140174
std::string entryName,
141175
std::optional<PerformanceEntryType> entryType) {
@@ -155,10 +189,10 @@ std::vector<PerformanceEntry> NativePerformance::getEntriesByName(
155189

156190
sortEntries(entries);
157191

158-
return entries;
192+
return toNativePerformanceEntries(entries);
159193
}
160194

161-
std::vector<PerformanceEntry> NativePerformance::getEntriesByType(
195+
std::vector<NativePerformanceEntry> NativePerformance::getEntriesByType(
162196
jsi::Runtime& /*rt*/,
163197
PerformanceEntryType entryType) {
164198
std::vector<PerformanceEntry> entries;
@@ -169,7 +203,7 @@ std::vector<PerformanceEntry> NativePerformance::getEntriesByType(
169203

170204
sortEntries(entries);
171205

172-
return entries;
206+
return toNativePerformanceEntries(entries);
173207
}
174208

175209
std::vector<std::pair<std::string, uint32_t>> NativePerformance::getEventCounts(
@@ -304,7 +338,7 @@ void NativePerformance::disconnect(jsi::Runtime& rt, jsi::Object observerObj) {
304338
observer->disconnect();
305339
}
306340

307-
std::vector<PerformanceEntry> NativePerformance::takeRecords(
341+
std::vector<NativePerformanceEntry> NativePerformance::takeRecords(
308342
jsi::Runtime& rt,
309343
jsi::Object observerObj,
310344
bool sort) {
@@ -320,7 +354,7 @@ std::vector<PerformanceEntry> NativePerformance::takeRecords(
320354
if (sort) {
321355
sortEntries(records);
322356
}
323-
return records;
357+
return toNativePerformanceEntries(records);
324358
}
325359

326360
std::vector<PerformanceEntryType>

packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,23 @@ struct Bridging<PerformanceEntryType> {
4949
}
5050
};
5151

52+
// Our Native Module codegen does not support JS type unions, so we use a
53+
// flattened object here as an intermediate format.
54+
struct NativePerformanceEntry {
55+
std::string name;
56+
PerformanceEntryType entryType;
57+
DOMHighResTimeStamp startTime;
58+
DOMHighResTimeStamp duration;
59+
60+
// For PerformanceEventTiming only
61+
std::optional<DOMHighResTimeStamp> processingStart;
62+
std::optional<DOMHighResTimeStamp> processingEnd;
63+
std::optional<PerformanceEntryInteractionId> interactionId;
64+
};
65+
5266
template <>
53-
struct Bridging<PerformanceEntry>
54-
: NativePerformanceRawPerformanceEntryBridging<PerformanceEntry> {};
67+
struct Bridging<NativePerformanceEntry>
68+
: NativePerformanceRawPerformanceEntryBridging<NativePerformanceEntry> {};
5569

5670
template <>
5771
struct Bridging<NativePerformancePerformanceObserverObserveOptions>
@@ -98,15 +112,15 @@ class NativePerformance : public NativePerformanceCxxSpec<NativePerformance> {
98112
#pragma mark - Performance Timeline (https://w3c.github.io/performance-timeline/#performance-timeline)
99113

100114
// https://www.w3.org/TR/performance-timeline/#getentries-method
101-
std::vector<PerformanceEntry> getEntries(jsi::Runtime& rt);
115+
std::vector<NativePerformanceEntry> getEntries(jsi::Runtime& rt);
102116

103117
// https://www.w3.org/TR/performance-timeline/#getentriesbytype-method
104-
std::vector<PerformanceEntry> getEntriesByType(
118+
std::vector<NativePerformanceEntry> getEntriesByType(
105119
jsi::Runtime& rt,
106120
PerformanceEntryType entryType);
107121

108122
// https://www.w3.org/TR/performance-timeline/#getentriesbyname-method
109-
std::vector<PerformanceEntry> getEntriesByName(
123+
std::vector<NativePerformanceEntry> getEntriesByName(
110124
jsi::Runtime& rt,
111125
std::string entryName,
112126
std::optional<PerformanceEntryType> entryType = std::nullopt);
@@ -125,7 +139,7 @@ class NativePerformance : public NativePerformanceCxxSpec<NativePerformance> {
125139
jsi::Object observer,
126140
NativePerformancePerformanceObserverObserveOptions options);
127141
void disconnect(jsi::Runtime& rt, jsi::Object observer);
128-
std::vector<PerformanceEntry> takeRecords(
142+
std::vector<NativePerformanceEntry> takeRecords(
129143
jsi::Runtime& rt,
130144
jsi::Object observerObj,
131145
// When called via `observer.takeRecords` it should be in insertion order.

packages/react-native/ReactCommon/react/performance/timeline/CircularBuffer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <algorithm>
1111
#include <functional>
1212
#include <vector>
13-
#include "PerformanceEntry.h"
1413

1514
namespace facebook::react {
1615

packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
#pragma once
99

1010
#include <react/timing/primitives.h>
11-
#include <optional>
1211
#include <string>
13-
#include <unordered_set>
12+
#include <variant>
1413

1514
namespace facebook::react {
1615

@@ -25,28 +24,50 @@ enum class PerformanceEntryType {
2524
_NEXT = 5,
2625
};
2726

28-
struct PerformanceEntry {
27+
struct AbstractPerformanceEntry {
2928
std::string name;
30-
PerformanceEntryType entryType;
3129
DOMHighResTimeStamp startTime;
3230
DOMHighResTimeStamp duration = 0;
31+
};
32+
33+
struct PerformanceMark : AbstractPerformanceEntry {
34+
static constexpr PerformanceEntryType entryType = PerformanceEntryType::MARK;
35+
};
36+
37+
struct PerformanceMeasure : AbstractPerformanceEntry {
38+
static constexpr PerformanceEntryType entryType =
39+
PerformanceEntryType::MEASURE;
40+
};
41+
42+
struct PerformanceEventTiming : AbstractPerformanceEntry {
43+
static constexpr PerformanceEntryType entryType = PerformanceEntryType::EVENT;
44+
DOMHighResTimeStamp processingStart;
45+
DOMHighResTimeStamp processingEnd;
46+
PerformanceEntryInteractionId interactionId;
47+
};
3348

34-
// For "event" entries only:
35-
std::optional<DOMHighResTimeStamp> processingStart;
36-
std::optional<DOMHighResTimeStamp> processingEnd;
37-
std::optional<PerformanceEntryInteractionId> interactionId;
49+
struct PerformanceLongTaskTiming : AbstractPerformanceEntry {
50+
static constexpr PerformanceEntryType entryType =
51+
PerformanceEntryType::LONGTASK;
3852
};
3953

40-
constexpr size_t NUM_PERFORMANCE_ENTRY_TYPES =
41-
(size_t)PerformanceEntryType::_NEXT - 1; // Valid types start from 1.
54+
using PerformanceEntry = std::variant<
55+
PerformanceMark,
56+
PerformanceMeasure,
57+
PerformanceEventTiming,
58+
PerformanceLongTaskTiming>;
4259

4360
struct PerformanceEntrySorter {
4461
bool operator()(const PerformanceEntry& lhs, const PerformanceEntry& rhs) {
45-
if (lhs.startTime != rhs.startTime) {
46-
return lhs.startTime < rhs.startTime;
47-
} else {
48-
return lhs.duration < rhs.duration;
49-
}
62+
return std::visit(
63+
[](const auto& left, const auto& right) {
64+
if (left.startTime != right.startTime) {
65+
return left.startTime < right.startTime;
66+
}
67+
return left.duration < right.duration;
68+
},
69+
lhs,
70+
rhs);
5071
}
5172
};
5273

packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryCircularBuffer.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include "PerformanceEntryCircularBuffer.h"
99

10+
#include <variant>
11+
1012
namespace facebook::react {
1113

1214
void PerformanceEntryCircularBuffer::add(const PerformanceEntry& entry) {
@@ -23,16 +25,23 @@ void PerformanceEntryCircularBuffer::getEntries(
2325
void PerformanceEntryCircularBuffer::getEntries(
2426
std::vector<PerformanceEntry>& target,
2527
const std::string& name) const {
26-
buffer_.getEntries(
27-
target, [&](const PerformanceEntry& e) { return e.name == name; });
28+
buffer_.getEntries(target, [&](const PerformanceEntry& entry) {
29+
return std::visit(
30+
[&name](const auto& entryData) { return entryData.name == name; },
31+
entry);
32+
});
2833
}
2934

3035
void PerformanceEntryCircularBuffer::clear() {
3136
buffer_.clear();
3237
}
3338

3439
void PerformanceEntryCircularBuffer::clear(const std::string& name) {
35-
buffer_.clear([&](const PerformanceEntry& e) { return e.name == name; });
40+
buffer_.clear([&](const PerformanceEntry& entry) {
41+
return std::visit(
42+
[&name](const auto& entryData) { return entryData.name == name; },
43+
entry);
44+
});
3645
}
3746

3847
} // namespace facebook::react

packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryKeyedBuffer.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@
1111
namespace facebook::react {
1212

1313
void PerformanceEntryKeyedBuffer::add(const PerformanceEntry& entry) {
14-
auto node = entryMap_.find(entry.name);
14+
auto name =
15+
std::visit([](const auto& entryData) { return entryData.name; }, entry);
16+
17+
auto node = entryMap_.find(name);
1518

1619
if (node != entryMap_.end()) {
1720
node->second.push_back(entry);
1821
} else {
19-
entryMap_.emplace(entry.name, std::vector<PerformanceEntry>{entry});
22+
entryMap_.emplace(name, std::vector<PerformanceEntry>{entry});
2023
}
2124
}
2225

packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryKeyedBuffer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#pragma once
99

1010
#include <optional>
11-
#include <string_view>
1211
#include <unordered_map>
1312
#include <vector>
1413
#include "PerformanceEntryBuffer.h"

0 commit comments

Comments
 (0)