GCC Code Coverage Report


ernie/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
258 / 281
91.8%
Branches:
426 / 936
45.5%
Functions:
30 / 33
90.9%

util/profiler.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 /// @file profiler.cpp
3 /// @brief Frame and zone recording for the in-process profiler, and zone-tree reports with their
4 /// text, JSON and trace exports.
5 #include "ernie/util/profiler.h"
6
7 #include <nlohmann/json.hpp>
8
9 #include <algorithm>
10 #include <atomic>
11 #include <chrono>
12 #include <cstdio>
13 #include <deque>
14 #include <functional>
15 #include <map>
16 #include <mutex>
17 #include <set>
18
19 namespace ernie::profiler {
20
21 namespace {
22
23 std::atomic<bool> cpuEnabled{false};
24 std::atomic<bool> gpuEnabled{false};
25
26 struct State {
27 std::mutex mutex;
28 Frame current;
29 std::deque<Frame> frames;
30 std::size_t history = 300;
31 std::vector<std::string> threadNames;
32 };
33
34 812 State& Global() {
35
5/6
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 727 times.
✓ Branch 3 taken 84 times.
✓ Branch 4 taken 1 time.
✓ Branch 6 taken 84 times.
✗ Branch 7 not taken.
812 static State state;
36 812 return state;
37 }
38
39 thread_local std::uint32_t zoneDepth = 0;
40
41 } // namespace
42
43 12 void SetEnabled(bool on) {
44 12 SetCpuEnabled(on);
45 12 SetGpuEnabled(on);
46 12 }
47
48 ✗ bool Enabled() {
49
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ return CpuEnabled() || GpuEnabled();
50 }
51
52 23 void SetCpuEnabled(bool on) {
53 23 cpuEnabled.store(on, std::memory_order_relaxed);
54 23 }
55
56 3525 bool CpuEnabled() {
57 3525 return cpuEnabled.load(std::memory_order_relaxed);
58 }
59
60 23 void SetGpuEnabled(bool on) {
61 23 gpuEnabled.store(on, std::memory_order_relaxed);
62 23 }
63
64 450 bool GpuEnabled() {
65 450 return gpuEnabled.load(std::memory_order_relaxed);
66 }
67
68 987 std::uint64_t Now() {
69 1974 return static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
70 987 std::chrono::steady_clock::now().time_since_epoch())
71 987 .count());
72 }
73
74 14 void BeginFrame() {
75 14 State& s = Global();
76 14 const std::uint64_t now = Now();
77 14 std::lock_guard lock(s.mutex);
78
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 if (s.current.start != 0) {
79 8 s.current.end = now;
80
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 s.frames.push_back(std::move(s.current));
81
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 while (s.frames.size() > s.history) {
82 ✗ s.frames.pop_front();
83 }
84 }
85
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 const std::uint64_t next = s.frames.empty() ? 0 : s.frames.back().index + 1;
86 14 s.current = Frame{};
87 14 s.current.index = next;
88 14 s.current.start = now;
89 14 }
90
91 558 std::uint64_t CurrentFrame() {
92 558 State& s = Global();
93 558 std::lock_guard lock(s.mutex);
94 558 return s.current.index;
95 558 }
96
97 12 std::vector<Frame> Frames() {
98 12 State& s = Global();
99 12 std::lock_guard lock(s.mutex);
100
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 return {s.frames.begin(), s.frames.end()};
101 12 }
102
103 ✗ void SetHistory(std::size_t frames) {
104 ✗ State& s = Global();
105 ✗ std::lock_guard lock(s.mutex);
106
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ s.history = std::max<std::size_t>(frames, 1);
107
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ while (s.frames.size() > s.history) {
108 ✗ s.frames.pop_front();
109 }
110 ✗ }
111
112 ✗ std::size_t History() {
113 ✗ State& s = Global();
114 ✗ std::lock_guard lock(s.mutex);
115 ✗ return s.history;
116 ✗ }
117
118 4 void Clear() {
119 4 State& s = Global();
120 4 std::lock_guard lock(s.mutex);
121 4 s.frames.clear();
122 4 s.current.cpu.clear();
123 4 s.current.gpu.clear();
124 4 }
125
126 176 std::uint32_t ThreadIndex() {
127 212 thread_local const std::uint32_t index = [] {
128 18 State& s = Global();
129 18 std::lock_guard lock(s.mutex);
130
2/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
36 s.threadNames.push_back("Thread " + std::to_string(s.threadNames.size()));
131 18 return static_cast<std::uint32_t>(s.threadNames.size() - 1);
132
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 158 times.
194 }();
133 176 return index;
134 }
135
136 11 void SetThreadName(std::string name) {
137 11 const std::uint32_t index = ThreadIndex();
138 11 State& s = Global();
139 11 std::lock_guard lock(s.mutex);
140 11 s.threadNames[index] = std::move(name);
141 11 }
142
143 8 std::vector<std::string> ThreadNames() {
144 8 State& s = Global();
145 8 std::lock_guard lock(s.mutex);
146
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 return s.threadNames;
147 8 }
148
149 25 const char* Intern(std::string_view name) {
150 25 static std::mutex mutex;
151 // Node-based: the strings never move.
152
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 21 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
25 static std::set<std::string, std::less<>> names;
153 25 std::lock_guard lock(mutex);
154 25 auto found = names.find(name);
155
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 6 times.
25 if (found == names.end()) {
156
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 found = names.emplace(name).first;
157 }
158 25 return found->c_str();
159 25 }
160
161 22 void AddGpuZone(std::uint64_t frame, const Zone& zone) {
162 22 State& s = Global();
163 22 std::lock_guard lock(s.mutex);
164
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (frame == s.current.index) {
165
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 s.current.gpu.push_back(zone);
166 return;
167 }
168
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ for (Frame& kept : s.frames) {
169
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (kept.index == frame) {
170
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ kept.gpu.push_back(zone);
171 ✗ return;
172 }
173 }
174 22 }
175
176 3525 ScopedZone::ScopedZone(const char* name) : name_(name) {
177
2/2
✓ Branch 1 taken 165 times.
✓ Branch 2 taken 3360 times.
3525 if (CpuEnabled()) {
178 165 active_ = true;
179 165 start_ = Now();
180 165 ++zoneDepth;
181 }
182 3525 }
183
184 3690 ScopedZone::~ScopedZone() {
185
2/2
✓ Branch 0 taken 3360 times.
✓ Branch 1 taken 165 times.
3525 if (!active_) {
186 3360 return;
187 }
188 165 --zoneDepth;
189 165 Zone zone{name_, start_, Now(), ThreadIndex(), zoneDepth};
190 165 State& s = Global();
191 165 std::lock_guard lock(s.mutex);
192 165 s.current.cpu.push_back(zone);
193 3525 }
194
195 // ----------------------------------------------------------------------------------------------
196 // Reports
197
198 namespace {
199
200 /// Adds `zones`, ordered as they started, to the tree under `roots`,
201 /// each under the zone one level out that ran last; `ms` and `calls`
202 /// gather sums (nanoseconds) to be averaged.
203 13 void Gather(std::vector<ReportNode>& roots, std::vector<const Zone*> zones) {
204 13 std::sort(zones.begin(), zones.end(), [](const Zone* a, const Zone* b) {
205
3/24
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 13 times.
✓ Branch 23 taken 6 times.
25 return a->start != b->start ? a->start < b->start : a->depth < b->depth;
206 });
207 13 std::vector<ReportNode*> path;
208
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 13 times.
45 for (const Zone* zone : zones) {
209
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
32 path.resize(std::min<std::size_t>(zone->depth, path.size()));
210
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 13 times.
32 std::vector<ReportNode>& siblings = path.empty() ? roots : path.back()->children;
211
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 12 times.
32 auto node = std::find_if(siblings.begin(), siblings.end(),
212
4/14
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 10 times.
✓ Branch 13 taken 4 times.
18 [&](const ReportNode& n) { return n.name == zone->name; });
213
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 12 times.
32 if (node == siblings.end()) {
214
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
20 siblings.emplace_back().name = zone->name;
215 20 node = siblings.end() - 1;
216 }
217
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 node->ms += static_cast<double>(zone->end - zone->start);
218 32 node->calls += 1.0;
219
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 path.push_back(&*node);
220 }
221 13 }
222
223 /// Turns `Gather`'s sums over `frames` frames into means and shares
224 /// of `totalMs`.
225 28 void Average(std::vector<ReportNode>& nodes, double frames, double totalMs) {
226
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 28 times.
48 for (ReportNode& node : nodes) {
227 20 node.ms = node.ms * 1e-6 / frames;
228 20 node.calls /= frames;
229
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 node.percent = totalMs > 0.0 ? 100.0 * node.ms / totalMs : 0.0;
230 20 Average(node.children, frames, totalMs);
231 }
232 28 }
233
234 32 void AddRows(const std::vector<ReportNode>& nodes, const ReportFilter& filter, std::uint32_t depth,
235 std::vector<ReportRow>& rows) {
236 // Siblings as they ran, or longest first (ties as they ran).
237 32 std::vector<const ReportNode*> order;
238
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 order.reserve(nodes.size());
239
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 32 times.
48 for (const ReportNode& node : nodes) {
240
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 order.push_back(&node);
241 }
242
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 28 times.
32 if (filter.byTime) {
243 4 std::stable_sort(order.begin(), order.end(),
244
1/18
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
1 [](const ReportNode* a, const ReportNode* b) { return a->ms > b->ms; });
245 }
246
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 32 times.
48 for (const ReportNode* node : order) {
247
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 15 times.
16 if (node->ms < filter.minMs) {
248 1 continue;
249 }
250
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 const std::size_t at = rows.size();
251
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 rows.push_back({node, depth, false});
252
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 time.
15 if (depth < filter.depth) {
253
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 AddRows(node->children, filter, depth + 1, rows);
254 }
255 15 rows[at].parent = rows.size() > at + 1;
256 }
257 32 }
258
259 8 nlohmann::json ToJson(const std::vector<ReportNode>& nodes) {
260 8 nlohmann::json zones = nlohmann::json::array();
261
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
14 for (const ReportNode& node : nodes) {
262
2/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 30 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
96 zones.push_back({{"name", node.name},
263 6 {"ms", node.ms},
264 6 {"calls", node.calls},
265 6 {"percent", node.percent},
266 6 {"children", ToJson(node.children)}});
267 }
268 8 return zones;
269
23/52
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 6 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 6 times.
✗ Branch 18 not taken.
✓ Branch 21 taken 6 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 6 times.
✗ Branch 25 not taken.
✓ Branch 28 taken 6 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 6 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 6 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 6 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 6 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 12 times.
✓ Branch 43 taken 6 times.
✓ Branch 44 taken 12 times.
✓ Branch 45 taken 6 times.
✓ Branch 46 taken 12 times.
✓ Branch 47 taken 6 times.
✓ Branch 48 taken 12 times.
✓ Branch 49 taken 6 times.
✓ Branch 50 taken 12 times.
✓ Branch 51 taken 6 times.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
84 }
270
271 5 std::string ThreadName(const std::vector<std::string>& names, std::uint32_t thread) {
272
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
7 return thread < names.size() ? names[thread] : "Thread " + std::to_string(thread);
273 }
274
275 } // namespace
276
277 12 Report Summarize(std::span<const Frame> frames, const std::vector<std::string>& threadNames) {
278 12 Report report;
279 12 std::map<std::uint32_t, std::vector<ReportNode>> threads;
280
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 12 times.
19 for (const Frame& frame : frames) {
281 7 report.cpuMs += static_cast<double>(frame.end - frame.start);
282 7 ++report.cpuFrames;
283 7 std::map<std::uint32_t, std::vector<const Zone*>> byThread;
284
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (const Zone& zone : frame.cpu) {
285
2/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
14 byThread[zone.thread].push_back(&zone);
286 }
287
3/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 7 times.
14 for (auto& [thread, zones] : byThread) {
288
2/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
7 Gather(threads[thread], std::move(zones));
289 }
290
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 6 times.
7 if (frame.gpu.empty()) {
291 1 continue;
292 }
293 6 ++report.gpuFrames;
294 6 std::vector<const Zone*> zones;
295
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
24 for (const Zone& zone : frame.gpu) {
296
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 zones.push_back(&zone);
297
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (zone.depth == 0) {
298 6 report.gpuMs += static_cast<double>(zone.end - zone.start);
299 }
300 }
301
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 Gather(report.gpu, std::move(zones));
302 7 }
303
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
12 if (report.gpuFrames > 0) {
304 4 const double count = static_cast<double>(report.gpuFrames);
305 4 report.gpuMs = report.gpuMs * 1e-6 / count;
306 4 Average(report.gpu, count, report.gpuMs);
307 }
308
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
12 if (report.cpuFrames > 0) {
309 4 const double count = static_cast<double>(report.cpuFrames);
310 4 report.cpuMs = report.cpuMs * 1e-6 / count;
311
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
8 for (auto& [thread, roots] : threads) {
312 4 Average(roots, count, report.cpuMs);
313
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 ReportNode node;
314
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 node.name = ThreadName(threadNames, thread);
315
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 for (const ReportNode& root : roots) {
316 4 node.ms += root.ms;
317 }
318 4 node.calls = 1.0;
319
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 node.percent = report.cpuMs > 0.0 ? 100.0 * node.ms / report.cpuMs : 0.0;
320 4 node.children = std::move(roots);
321
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 report.cpu.push_back(std::move(node));
322 4 }
323 }
324 12 return report;
325 12 }
326
327 18 std::vector<ReportRow> Rows(const std::vector<ReportNode>& nodes, const ReportFilter& filter) {
328 18 std::vector<ReportRow> rows;
329
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 AddRows(nodes, filter, 0, rows);
330 18 return rows;
331 ✗ }
332
333 1 std::string ReportText(const Report& report, const ReportFilter& filter) {
334
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 std::string text;
335 1 char line[256];
336 3 const auto section = [&](const char* title, const std::vector<ReportNode>& nodes,
337 double totalMs, std::size_t frames) {
338 // The section's total heads it; its zones below, indented.
339 2 std::snprintf(line, sizeof(line), "%-56s %12s %10s\n", "", "Duration (ms)", "Percent");
340 2 text += line;
341 4 std::snprintf(line, sizeof(line), "%-56s %12.3f (%zu frames)\n",
342 4 (std::string(title) + " total").c_str(), totalMs, frames);
343 2 text += line;
344
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
8 for (const ReportRow& row : Rows(nodes, filter)) {
345
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 const std::string name = std::string(2 * (row.depth + 1), ' ') + row.node->name;
346 6 std::snprintf(line, sizeof(line), "%-56s %12.3f %9.2f%%\n", name.c_str(), row.node->ms,
347
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 row.node->percent);
348
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 text += line;
349 8 }
350 2 text += "\n";
351 2 };
352
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 section("GPU", report.gpu, report.gpuMs, report.gpuFrames);
353
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 section("CPU", report.cpu, report.cpuMs, report.cpuFrames);
354 1 return text;
355 ✗ }
356
357 1 std::string ReportJson(const Report& report) {
358 1 const nlohmann::json json = {
359 {"gpu",
360 1 {{"ms", report.gpuMs}, {"frames", report.gpuFrames}, {"zones", ToJson(report.gpu)}}},
361 {"cpu",
362
2/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
26 {{"ms", report.cpuMs}, {"frames", report.cpuFrames}, {"zones", ToJson(report.cpu)}}}};
363 1 return json.dump(2);
364
42/98
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 time.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 time.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 time.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 time.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 time.
✗ Branch 25 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
✓ Branch 30 taken 1 time.
✗ Branch 31 not taken.
✓ Branch 33 taken 1 time.
✗ Branch 34 not taken.
✓ Branch 36 taken 1 time.
✗ Branch 37 not taken.
✓ Branch 40 taken 1 time.
✗ Branch 41 not taken.
✓ Branch 43 taken 1 time.
✗ Branch 44 not taken.
✓ Branch 47 taken 1 time.
✗ Branch 48 not taken.
✓ Branch 50 taken 1 time.
✗ Branch 51 not taken.
✓ Branch 53 taken 1 time.
✗ Branch 54 not taken.
✓ Branch 56 taken 1 time.
✗ Branch 57 not taken.
✓ Branch 59 taken 1 time.
✗ Branch 60 not taken.
✓ Branch 62 taken 1 time.
✗ Branch 63 not taken.
✓ Branch 65 taken 1 time.
✗ Branch 66 not taken.
✓ Branch 67 taken 1 time.
✓ Branch 68 taken 2 times.
✓ Branch 69 taken 1 time.
✓ Branch 70 taken 3 times.
✓ Branch 71 taken 2 times.
✓ Branch 72 taken 1 time.
✓ Branch 73 taken 2 times.
✓ Branch 74 taken 1 time.
✓ Branch 75 taken 2 times.
✓ Branch 76 taken 1 time.
✓ Branch 77 taken 1 time.
✓ Branch 78 taken 2 times.
✓ Branch 79 taken 1 time.
✓ Branch 80 taken 3 times.
✓ Branch 81 taken 2 times.
✓ Branch 82 taken 1 time.
✓ Branch 83 taken 2 times.
✓ Branch 84 taken 1 time.
✓ Branch 85 taken 2 times.
✓ Branch 86 taken 1 time.
✓ Branch 88 taken 1 time.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
32 }
365
366 1 std::string TraceJson(std::span<const Frame> frames, const std::vector<std::string>& threadNames) {
367 1 constexpr int kCpu = 1;
368 1 constexpr int kGpu = 2;
369 1 nlohmann::json events = nlohmann::json::array();
370
2/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
16 events.push_back(
371 {{"name", "process_name"}, {"ph", "M"}, {"pid", kCpu}, {"args", {{"name", "CPU"}}}});
372
2/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
16 events.push_back(
373 {{"name", "process_name"}, {"ph", "M"}, {"pid", kGpu}, {"args", {{"name", "GPU"}}}});
374
2/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 time.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
19 events.push_back({{"name", "thread_name"},
375 {"ph", "M"},
376 {"pid", kGpu},
377 2 {"tid", 0},
378 {"args", {{"name", "Queue"}}}});
379 1 if (frames.empty()) {
380
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ return nlohmann::json{{"traceEvents", events}}.dump();
381 }
382 1 const std::uint64_t origin = frames.front().start;
383 25 const auto us = [](double ns) { return ns * 1e-3; };
384 1 std::map<std::uint32_t, bool> threads;
385
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 for (const Frame& frame : frames) {
386
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 2 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
42 events.push_back({{"name", "Frame " + std::to_string(frame.index)},
387 {"ph", "X"},
388 {"pid", kCpu},
389 {"tid", "frames"},
390 4 {"ts", us(static_cast<double>(frame.start - origin))},
391 4 {"dur", us(static_cast<double>(frame.end - frame.start))}});
392
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (const Zone& zone : frame.cpu) {
393
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 threads[zone.thread] = true;
394
2/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 4 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
76 events.push_back({{"name", zone.name},
395 {"ph", "X"},
396 {"pid", kCpu},
397 4 {"tid", zone.thread},
398 8 {"ts", us(static_cast<double>(zone.start - origin))},
399 8 {"dur", us(static_cast<double>(zone.end - zone.start))}});
400 }
401 2 std::uint64_t base = UINT64_MAX;
402
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (const Zone& zone : frame.gpu) {
403
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
8 base = std::min(base, zone.start);
404 }
405
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (const Zone& zone : frame.gpu) {
406
2/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
114 events.push_back({{"name", zone.name},
407 {"ph", "X"},
408 {"pid", kGpu},
409 12 {"tid", 0},
410 12 {"ts", us(static_cast<double>(frame.start - origin) +
411 6 static_cast<double>(zone.start - base))},
412 12 {"dur", us(static_cast<double>(zone.end - zone.start))}});
413 }
414 }
415
3/4
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
2 for (const auto& [thread, used] : threads) {
416
2/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 time.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
19 events.push_back({{"name", "thread_name"},
417 {"ph", "M"},
418 {"pid", kCpu},
419 {"tid", thread},
420 ✗ {"args", {{"name", ThreadName(threadNames, thread)}}}});
421 }
422
3/6
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 time.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
7 return nlohmann::json{{"traceEvents", events}, {"displayTimeUnit", "ms"}}.dump();
423
210/500
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 time.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 time.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 time.
✗ Branch 20 not taken.
✓ Branch 23 taken 1 time.
✗ Branch 24 not taken.
✓ Branch 26 taken 1 time.
✗ Branch 27 not taken.
✓ Branch 29 taken 1 time.
✗ Branch 30 not taken.
✓ Branch 32 taken 1 time.
✗ Branch 33 not taken.
✓ Branch 35 taken 1 time.
✗ Branch 36 not taken.
✓ Branch 38 taken 1 time.
✗ Branch 39 not taken.
✓ Branch 41 taken 1 time.
✗ Branch 42 not taken.
✗ Branch 44 not taken.
✓ Branch 45 taken 1 time.
✓ Branch 46 taken 2 times.
✓ Branch 47 taken 1 time.
✓ Branch 48 taken 1 time.
✓ Branch 49 taken 1 time.
✓ Branch 50 taken 2 times.
✓ Branch 51 taken 1 time.
✓ Branch 52 taken 2 times.
✓ Branch 53 taken 1 time.
✓ Branch 54 taken 2 times.
✓ Branch 55 taken 1 time.
✓ Branch 56 taken 2 times.
✓ Branch 57 taken 1 time.
✓ Branch 59 taken 1 time.
✗ Branch 60 not taken.
✓ Branch 62 taken 1 time.
✗ Branch 63 not taken.
✓ Branch 65 taken 1 time.
✗ Branch 66 not taken.
✓ Branch 68 taken 1 time.
✗ Branch 69 not taken.
✓ Branch 71 taken 1 time.
✗ Branch 72 not taken.
✓ Branch 74 taken 1 time.
✗ Branch 75 not taken.
✓ Branch 77 taken 1 time.
✗ Branch 78 not taken.
✓ Branch 81 taken 1 time.
✗ Branch 82 not taken.
✓ Branch 84 taken 1 time.
✗ Branch 85 not taken.
✓ Branch 87 taken 1 time.
✗ Branch 88 not taken.
✓ Branch 90 taken 1 time.
✗ Branch 91 not taken.
✓ Branch 93 taken 1 time.
✗ Branch 94 not taken.
✓ Branch 96 taken 1 time.
✗ Branch 97 not taken.
✓ Branch 99 taken 1 time.
✗ Branch 100 not taken.
✗ Branch 102 not taken.
✓ Branch 103 taken 1 time.
✓ Branch 104 taken 2 times.
✓ Branch 105 taken 1 time.
✓ Branch 106 taken 1 time.
✓ Branch 107 taken 1 time.
✓ Branch 108 taken 2 times.
✓ Branch 109 taken 1 time.
✓ Branch 110 taken 2 times.
✓ Branch 111 taken 1 time.
✓ Branch 112 taken 2 times.
✓ Branch 113 taken 1 time.
✓ Branch 114 taken 2 times.
✓ Branch 115 taken 1 time.
✓ Branch 117 taken 1 time.
✗ Branch 118 not taken.
✓ Branch 120 taken 1 time.
✗ Branch 121 not taken.
✓ Branch 123 taken 1 time.
✗ Branch 124 not taken.
✓ Branch 126 taken 1 time.
✗ Branch 127 not taken.
✓ Branch 129 taken 1 time.
✗ Branch 130 not taken.
✓ Branch 132 taken 1 time.
✗ Branch 133 not taken.
✓ Branch 135 taken 1 time.
✗ Branch 136 not taken.
✓ Branch 139 taken 1 time.
✗ Branch 140 not taken.
✓ Branch 142 taken 1 time.
✗ Branch 143 not taken.
✓ Branch 146 taken 1 time.
✗ Branch 147 not taken.
✓ Branch 149 taken 1 time.
✗ Branch 150 not taken.
✓ Branch 152 taken 1 time.
✗ Branch 153 not taken.
✓ Branch 155 taken 1 time.
✗ Branch 156 not taken.
✓ Branch 158 taken 1 time.
✗ Branch 159 not taken.
✓ Branch 161 taken 1 time.
✗ Branch 162 not taken.
✓ Branch 164 taken 1 time.
✗ Branch 165 not taken.
✗ Branch 167 not taken.
✓ Branch 168 taken 1 time.
✓ Branch 169 taken 2 times.
✓ Branch 170 taken 1 time.
✓ Branch 171 taken 1 time.
✓ Branch 172 taken 1 time.
✓ Branch 173 taken 2 times.
✓ Branch 174 taken 1 time.
✓ Branch 175 taken 2 times.
✓ Branch 176 taken 1 time.
✓ Branch 177 taken 2 times.
✓ Branch 178 taken 1 time.
✓ Branch 179 taken 2 times.
✓ Branch 180 taken 1 time.
✓ Branch 181 taken 2 times.
✓ Branch 182 taken 1 time.
✗ Branch 183 not taken.
✓ Branch 184 taken 1 time.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 192 not taken.
✗ Branch 193 not taken.
✗ Branch 195 not taken.
✗ Branch 196 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✓ Branch 200 taken 2 times.
✗ Branch 201 not taken.
✓ Branch 203 taken 2 times.
✗ Branch 204 not taken.
✓ Branch 206 taken 2 times.
✗ Branch 207 not taken.
✓ Branch 209 taken 2 times.
✗ Branch 210 not taken.
✓ Branch 212 taken 2 times.
✗ Branch 213 not taken.
✓ Branch 215 taken 2 times.
✗ Branch 216 not taken.
✓ Branch 218 taken 2 times.
✗ Branch 219 not taken.
✓ Branch 222 taken 2 times.
✗ Branch 223 not taken.
✓ Branch 225 taken 2 times.
✗ Branch 226 not taken.
✓ Branch 228 taken 2 times.
✗ Branch 229 not taken.
✓ Branch 231 taken 2 times.
✗ Branch 232 not taken.
✓ Branch 234 taken 2 times.
✗ Branch 235 not taken.
✓ Branch 238 taken 2 times.
✗ Branch 239 not taken.
✓ Branch 241 taken 2 times.
✗ Branch 242 not taken.
✓ Branch 245 taken 2 times.
✗ Branch 246 not taken.
✗ Branch 248 not taken.
✓ Branch 249 taken 2 times.
✓ Branch 250 taken 4 times.
✓ Branch 251 taken 2 times.
✓ Branch 252 taken 4 times.
✓ Branch 253 taken 2 times.
✓ Branch 254 taken 4 times.
✓ Branch 255 taken 2 times.
✓ Branch 256 taken 4 times.
✓ Branch 257 taken 2 times.
✓ Branch 258 taken 4 times.
✓ Branch 259 taken 2 times.
✓ Branch 260 taken 4 times.
✓ Branch 261 taken 2 times.
✓ Branch 263 taken 4 times.
✗ Branch 264 not taken.
✓ Branch 266 taken 4 times.
✗ Branch 267 not taken.
✓ Branch 269 taken 4 times.
✗ Branch 270 not taken.
✓ Branch 272 taken 4 times.
✗ Branch 273 not taken.
✓ Branch 275 taken 4 times.
✗ Branch 276 not taken.
✓ Branch 278 taken 4 times.
✗ Branch 279 not taken.
✓ Branch 281 taken 4 times.
✗ Branch 282 not taken.
✓ Branch 285 taken 4 times.
✗ Branch 286 not taken.
✓ Branch 288 taken 4 times.
✗ Branch 289 not taken.
✓ Branch 292 taken 4 times.
✗ Branch 293 not taken.
✓ Branch 295 taken 4 times.
✗ Branch 296 not taken.
✓ Branch 299 taken 4 times.
✗ Branch 300 not taken.
✓ Branch 302 taken 4 times.
✗ Branch 303 not taken.
✓ Branch 306 taken 4 times.
✗ Branch 307 not taken.
✗ Branch 309 not taken.
✓ Branch 310 taken 4 times.
✓ Branch 311 taken 8 times.
✓ Branch 312 taken 4 times.
✓ Branch 313 taken 8 times.
✓ Branch 314 taken 4 times.
✓ Branch 315 taken 8 times.
✓ Branch 316 taken 4 times.
✓ Branch 317 taken 8 times.
✓ Branch 318 taken 4 times.
✓ Branch 319 taken 8 times.
✓ Branch 320 taken 4 times.
✓ Branch 321 taken 8 times.
✓ Branch 322 taken 4 times.
✓ Branch 324 taken 6 times.
✗ Branch 325 not taken.
✓ Branch 327 taken 6 times.
✗ Branch 328 not taken.
✓ Branch 330 taken 6 times.
✗ Branch 331 not taken.
✓ Branch 333 taken 6 times.
✗ Branch 334 not taken.
✓ Branch 336 taken 6 times.
✗ Branch 337 not taken.
✓ Branch 339 taken 6 times.
✗ Branch 340 not taken.
✓ Branch 342 taken 6 times.
✗ Branch 343 not taken.
✓ Branch 346 taken 6 times.
✗ Branch 347 not taken.
✓ Branch 349 taken 6 times.
✗ Branch 350 not taken.
✓ Branch 353 taken 6 times.
✗ Branch 354 not taken.
✓ Branch 356 taken 6 times.
✗ Branch 357 not taken.
✓ Branch 360 taken 6 times.
✗ Branch 361 not taken.
✓ Branch 363 taken 6 times.
✗ Branch 364 not taken.
✓ Branch 367 taken 6 times.
✗ Branch 368 not taken.
✗ Branch 370 not taken.
✓ Branch 371 taken 6 times.
✓ Branch 372 taken 12 times.
✓ Branch 373 taken 6 times.
✓ Branch 374 taken 12 times.
✓ Branch 375 taken 6 times.
✓ Branch 376 taken 12 times.
✓ Branch 377 taken 6 times.
✓ Branch 378 taken 12 times.
✓ Branch 379 taken 6 times.
✓ Branch 380 taken 12 times.
✓ Branch 381 taken 6 times.
✓ Branch 382 taken 12 times.
✓ Branch 383 taken 6 times.
✓ Branch 385 taken 1 time.
✗ Branch 386 not taken.
✓ Branch 388 taken 1 time.
✗ Branch 389 not taken.
✓ Branch 391 taken 1 time.
✗ Branch 392 not taken.
✓ Branch 394 taken 1 time.
✗ Branch 395 not taken.
✓ Branch 397 taken 1 time.
✗ Branch 398 not taken.
✓ Branch 400 taken 1 time.
✗ Branch 401 not taken.
✓ Branch 403 taken 1 time.
✗ Branch 404 not taken.
✓ Branch 407 taken 1 time.
✗ Branch 408 not taken.
✓ Branch 410 taken 1 time.
✗ Branch 411 not taken.
✓ Branch 414 taken 1 time.
✗ Branch 415 not taken.
✓ Branch 417 taken 1 time.
✗ Branch 418 not taken.
✓ Branch 420 taken 1 time.
✗ Branch 421 not taken.
✓ Branch 423 taken 1 time.
✗ Branch 424 not taken.
✓ Branch 426 taken 1 time.
✗ Branch 427 not taken.
✓ Branch 429 taken 1 time.
✗ Branch 430 not taken.
✓ Branch 432 taken 1 time.
✗ Branch 433 not taken.
✗ Branch 435 not taken.
✓ Branch 436 taken 1 time.
✓ Branch 437 taken 2 times.
✓ Branch 438 taken 1 time.
✓ Branch 439 taken 1 time.
✓ Branch 440 taken 1 time.
✓ Branch 441 taken 2 times.
✓ Branch 442 taken 1 time.
✓ Branch 443 taken 2 times.
✓ Branch 444 taken 1 time.
✓ Branch 445 taken 2 times.
✓ Branch 446 taken 1 time.
✓ Branch 447 taken 2 times.
✓ Branch 448 taken 1 time.
✓ Branch 449 taken 2 times.
✓ Branch 450 taken 1 time.
✓ Branch 452 taken 1 time.
✗ Branch 453 not taken.
✓ Branch 455 taken 1 time.
✗ Branch 456 not taken.
✓ Branch 458 taken 1 time.
✗ Branch 459 not taken.
✓ Branch 461 taken 1 time.
✗ Branch 462 not taken.
✓ Branch 464 taken 1 time.
✗ Branch 465 not taken.
✓ Branch 467 taken 1 time.
✗ Branch 468 not taken.
✓ Branch 470 taken 1 time.
✗ Branch 471 not taken.
✓ Branch 472 taken 2 times.
✓ Branch 473 taken 1 time.
✓ Branch 474 taken 2 times.
✓ Branch 475 taken 1 time.
✗ Branch 478 not taken.
✗ Branch 479 not taken.
✗ Branch 480 not taken.
✗ Branch 481 not taken.
✗ Branch 482 not taken.
✗ Branch 483 not taken.
✗ Branch 484 not taken.
✗ Branch 485 not taken.
✗ Branch 487 not taken.
✗ Branch 488 not taken.
✗ Branch 490 not taken.
✗ Branch 491 not taken.
✗ Branch 492 not taken.
✗ Branch 493 not taken.
✗ Branch 494 not taken.
✗ Branch 495 not taken.
✗ Branch 497 not taken.
✗ Branch 498 not taken.
✗ Branch 499 not taken.
✗ Branch 500 not taken.
✗ Branch 502 not taken.
✗ Branch 503 not taken.
✗ Branch 505 not taken.
✗ Branch 506 not taken.
✗ Branch 507 not taken.
✗ Branch 508 not taken.
✗ Branch 509 not taken.
✗ Branch 510 not taken.
✗ Branch 511 not taken.
✗ Branch 512 not taken.
✗ Branch 514 not taken.
✗ Branch 515 not taken.
✗ Branch 517 not taken.
✗ Branch 518 not taken.
✗ Branch 519 not taken.
✗ Branch 520 not taken.
✗ Branch 521 not taken.
✗ Branch 522 not taken.
✗ Branch 524 not taken.
✗ Branch 525 not taken.
✗ Branch 526 not taken.
✗ Branch 527 not taken.
✗ Branch 529 not taken.
✗ Branch 530 not taken.
✗ Branch 532 not taken.
✗ Branch 533 not taken.
✗ Branch 534 not taken.
✗ Branch 535 not taken.
✗ Branch 536 not taken.
✗ Branch 537 not taken.
✗ Branch 538 not taken.
✗ Branch 539 not taken.
✗ Branch 541 not taken.
✗ Branch 542 not taken.
✗ Branch 544 not taken.
✗ Branch 545 not taken.
✗ Branch 546 not taken.
✗ Branch 547 not taken.
✗ Branch 548 not taken.
✗ Branch 549 not taken.
✗ Branch 550 not taken.
✗ Branch 551 not taken.
✗ Branch 553 not taken.
✗ Branch 554 not taken.
✗ Branch 555 not taken.
✗ Branch 556 not taken.
✗ Branch 558 not taken.
✗ Branch 559 not taken.
✗ Branch 561 not taken.
✗ Branch 562 not taken.
✗ Branch 563 not taken.
✗ Branch 564 not taken.
✗ Branch 566 not taken.
✗ Branch 567 not taken.
✗ Branch 568 not taken.
✗ Branch 569 not taken.
✗ Branch 570 not taken.
✗ Branch 571 not taken.
✗ Branch 572 not taken.
✗ Branch 573 not taken.
✗ Branch 575 not taken.
✗ Branch 576 not taken.
✗ Branch 577 not taken.
✗ Branch 578 not taken.
✗ Branch 579 not taken.
✗ Branch 580 not taken.
✗ Branch 582 not taken.
✗ Branch 583 not taken.
✗ Branch 584 not taken.
✗ Branch 585 not taken.
✗ Branch 587 not taken.
✗ Branch 588 not taken.
✗ Branch 590 not taken.
✗ Branch 591 not taken.
✗ Branch 592 not taken.
✗ Branch 593 not taken.
✗ Branch 594 not taken.
✗ Branch 595 not taken.
✗ Branch 596 not taken.
✗ Branch 597 not taken.
✗ Branch 598 not taken.
✗ Branch 599 not taken.
✗ Branch 600 not taken.
✗ Branch 601 not taken.
✗ Branch 603 not taken.
✗ Branch 604 not taken.
✗ Branch 605 not taken.
✗ Branch 606 not taken.
✗ Branch 608 not taken.
✗ Branch 609 not taken.
✗ Branch 611 not taken.
✗ Branch 612 not taken.
✗ Branch 613 not taken.
✗ Branch 614 not taken.
✗ Branch 615 not taken.
✗ Branch 616 not taken.
✗ Branch 617 not taken.
✗ Branch 618 not taken.
✗ Branch 619 not taken.
✗ Branch 620 not taken.
✗ Branch 621 not taken.
✗ Branch 622 not taken.
✗ Branch 624 not taken.
✗ Branch 625 not taken.
✗ Branch 626 not taken.
✗ Branch 627 not taken.
✗ Branch 629 not taken.
✗ Branch 630 not taken.
✗ Branch 632 not taken.
✗ Branch 633 not taken.
✗ Branch 634 not taken.
✗ Branch 635 not taken.
✗ Branch 636 not taken.
✗ Branch 637 not taken.
✗ Branch 638 not taken.
✗ Branch 639 not taken.
✗ Branch 641 not taken.
✗ Branch 642 not taken.
✗ Branch 644 not taken.
✗ Branch 645 not taken.
✗ Branch 646 not taken.
✗ Branch 647 not taken.
✗ Branch 648 not taken.
✗ Branch 649 not taken.
✗ Branch 650 not taken.
✗ Branch 651 not taken.
✗ Branch 653 not taken.
✗ Branch 654 not taken.
✗ Branch 655 not taken.
✗ Branch 656 not taken.
✗ Branch 658 not taken.
✗ Branch 659 not taken.
✗ Branch 661 not taken.
✗ Branch 662 not taken.
✗ Branch 663 not taken.
✗ Branch 664 not taken.
✗ Branch 666 not taken.
✗ Branch 667 not taken.
✗ Branch 668 not taken.
✗ Branch 669 not taken.
✗ Branch 671 not taken.
✗ Branch 672 not taken.
234 }
424
425 } // namespace ernie::profiler
426