Skip to content

Commit a4bdd03

Browse files
DevmateUtgenCppGeneralFBOrg Botfacebook-github-bot
authored andcommitted
xplat/js/react-native-github/packages/react-native/ReactCommon/react/renderer/telemetry/SurfaceTelemetry.cpp
Differential Revision: D114183414
1 parent 568eaa6 commit a4bdd03

1 file changed

Lines changed: 170 additions & 0 deletions

File tree

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
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+
#include <chrono>
9+
#include <memory>
10+
11+
#include <gtest/gtest.h>
12+
13+
#include <react/renderer/telemetry/SurfaceTelemetry.h>
14+
#include <react/renderer/telemetry/TransactionTelemetry.h>
15+
#include <react/utils/Telemetry.h>
16+
17+
using namespace facebook::react;
18+
19+
namespace {
20+
21+
using namespace std::chrono_literals;
22+
23+
/*
24+
* Builds a fully-completed `TransactionTelemetry` with deterministic phase
25+
* durations by driving a lambda-backed clock whose time we advance explicitly
26+
* between each `will`/`did` pair. `SurfaceTelemetry::incorporate` reads every
27+
* phase's start/end time, so all four phases (diff, layout, commit, mount) must
28+
* be signaled or the telemetry getters would assert.
29+
*/
30+
TransactionTelemetry makeCompletedTelemetry(
31+
std::chrono::milliseconds diff,
32+
std::chrono::milliseconds layout,
33+
std::chrono::milliseconds commit,
34+
std::chrono::milliseconds mount,
35+
std::chrono::milliseconds textMeasurePerCall,
36+
int numberOfTextMeasurements,
37+
int revisionNumber) {
38+
auto now = std::make_shared<TelemetryTimePoint>();
39+
auto telemetry = TransactionTelemetry{[now]() { return *now; }};
40+
41+
telemetry.willDiff();
42+
*now += diff;
43+
telemetry.didDiff();
44+
45+
telemetry.willLayout();
46+
*now += layout;
47+
telemetry.didLayout();
48+
49+
for (int i = 0; i < numberOfTextMeasurements; ++i) {
50+
telemetry.willMeasureText();
51+
*now += textMeasurePerCall;
52+
telemetry.didMeasureText();
53+
}
54+
55+
telemetry.willCommit();
56+
*now += commit;
57+
telemetry.didCommit();
58+
59+
telemetry.willMount();
60+
*now += mount;
61+
telemetry.didMount();
62+
63+
telemetry.setRevisionNumber(revisionNumber);
64+
return telemetry;
65+
}
66+
67+
} // namespace
68+
69+
TEST(SurfaceTelemetryTest, incorporateAggregatesSingleTransaction) {
70+
auto telemetry = makeCompletedTelemetry(
71+
/* diff */ 10ms,
72+
/* layout */ 20ms,
73+
/* commit */ 30ms,
74+
/* mount */ 40ms,
75+
/* textMeasurePerCall */ 5ms,
76+
/* numberOfTextMeasurements */ 3,
77+
/* revisionNumber */ 7);
78+
79+
auto surface = SurfaceTelemetry{};
80+
surface.incorporate(telemetry, /* numberOfMutations */ 11);
81+
82+
EXPECT_EQ(telemetryDurationToMilliseconds(surface.getDiffTime()), 10);
83+
EXPECT_EQ(telemetryDurationToMilliseconds(surface.getLayoutTime()), 20);
84+
EXPECT_EQ(telemetryDurationToMilliseconds(surface.getCommitTime()), 30);
85+
EXPECT_EQ(telemetryDurationToMilliseconds(surface.getMountTime()), 40);
86+
EXPECT_EQ(telemetryDurationToMilliseconds(surface.getTextMeasureTime()), 15);
87+
88+
EXPECT_EQ(surface.getNumberOfTransactions(), 1);
89+
EXPECT_EQ(surface.getNumberOfMutations(), 11);
90+
EXPECT_EQ(surface.getNumberOfTextMeasurements(), 3);
91+
EXPECT_EQ(surface.getLastRevisionNumber(), 7);
92+
EXPECT_EQ(surface.getRecentTransactionTelemetries().size(), 1);
93+
}
94+
95+
TEST(SurfaceTelemetryTest, incorporateAccumulatesAcrossTransactions) {
96+
auto first = makeCompletedTelemetry(
97+
/* diff */ 10ms,
98+
/* layout */ 20ms,
99+
/* commit */ 30ms,
100+
/* mount */ 40ms,
101+
/* textMeasurePerCall */ 5ms,
102+
/* numberOfTextMeasurements */ 2,
103+
/* revisionNumber */ 3);
104+
auto second = makeCompletedTelemetry(
105+
/* diff */ 1ms,
106+
/* layout */ 2ms,
107+
/* commit */ 3ms,
108+
/* mount */ 4ms,
109+
/* textMeasurePerCall */ 7ms,
110+
/* numberOfTextMeasurements */ 1,
111+
/* revisionNumber */ 9);
112+
113+
auto surface = SurfaceTelemetry{};
114+
surface.incorporate(first, /* numberOfMutations */ 4);
115+
surface.incorporate(second, /* numberOfMutations */ 6);
116+
117+
EXPECT_EQ(telemetryDurationToMilliseconds(surface.getDiffTime()), 11);
118+
EXPECT_EQ(telemetryDurationToMilliseconds(surface.getLayoutTime()), 22);
119+
EXPECT_EQ(telemetryDurationToMilliseconds(surface.getCommitTime()), 33);
120+
EXPECT_EQ(telemetryDurationToMilliseconds(surface.getMountTime()), 44);
121+
EXPECT_EQ(telemetryDurationToMilliseconds(surface.getTextMeasureTime()), 17);
122+
123+
EXPECT_EQ(surface.getNumberOfTransactions(), 2);
124+
EXPECT_EQ(surface.getNumberOfMutations(), 10);
125+
EXPECT_EQ(surface.getNumberOfTextMeasurements(), 3);
126+
// The last revision number must reflect the most recently incorporated
127+
// transaction, not an aggregate.
128+
EXPECT_EQ(surface.getLastRevisionNumber(), 9);
129+
EXPECT_EQ(surface.getRecentTransactionTelemetries().size(), 2);
130+
}
131+
132+
TEST(SurfaceTelemetryTest, recentTransactionTelemetriesRetainAllAtCapBoundary) {
133+
const auto cap =
134+
static_cast<int>(SurfaceTelemetry::kMaxNumberOfRecordedCommitTelemetries);
135+
136+
auto surface = SurfaceTelemetry{};
137+
for (int revision = 1; revision <= cap; ++revision) {
138+
auto telemetry = makeCompletedTelemetry(
139+
1ms, 1ms, 1ms, 1ms, 0ms, /* numberOfTextMeasurements */ 0, revision);
140+
surface.incorporate(telemetry, /* numberOfMutations */ 1);
141+
}
142+
143+
auto recent = surface.getRecentTransactionTelemetries();
144+
// Exactly `cap` transactions fit without any eviction.
145+
EXPECT_EQ(recent.size(), static_cast<size_t>(cap));
146+
EXPECT_EQ(recent.front().getRevisionNumber(), 1);
147+
EXPECT_EQ(recent.back().getRevisionNumber(), cap);
148+
}
149+
150+
TEST(SurfaceTelemetryTest, recentTransactionTelemetriesEvictOldestBeyondCap) {
151+
const auto cap =
152+
static_cast<int>(SurfaceTelemetry::kMaxNumberOfRecordedCommitTelemetries);
153+
const int total = cap + 4;
154+
155+
auto surface = SurfaceTelemetry{};
156+
for (int revision = 1; revision <= total; ++revision) {
157+
auto telemetry = makeCompletedTelemetry(
158+
1ms, 1ms, 1ms, 1ms, 0ms, /* numberOfTextMeasurements */ 0, revision);
159+
surface.incorporate(telemetry, /* numberOfMutations */ 1);
160+
}
161+
162+
auto recent = surface.getRecentTransactionTelemetries();
163+
// The buffer is capped, but the running transaction counter is not.
164+
EXPECT_EQ(recent.size(), static_cast<size_t>(cap));
165+
EXPECT_EQ(surface.getNumberOfTransactions(), total);
166+
// The oldest `total - cap` transactions are evicted in FIFO order, so the
167+
// retained window is [total - cap + 1, total].
168+
EXPECT_EQ(recent.front().getRevisionNumber(), total - cap + 1);
169+
EXPECT_EQ(recent.back().getRevisionNumber(), total);
170+
}

0 commit comments

Comments
 (0)