1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <benchmark/benchmark.h>
18
19 #include <cstddef>
20 #include <cstdint>
21 #include <initializer_list>
22 #include <optional>
23 #include <string>
24 #include <string_view>
25 #include <vector>
26
27 #include "perfetto/base/logging.h"
28 #include "perfetto/ext/base/file_utils.h"
29 #include "perfetto/ext/base/string_utils.h"
30 #include "perfetto/ext/base/string_view.h"
31 #include "perfetto/trace_processor/basic_types.h"
32 #include "src/base/test/utils.h"
33 #include "src/trace_processor/containers/string_pool.h"
34 #include "src/trace_processor/db/column/types.h"
35 #include "src/trace_processor/db/table.h"
36 #include "src/trace_processor/tables/metadata_tables_py.h"
37 #include "src/trace_processor/tables/profiler_tables_py.h"
38 #include "src/trace_processor/tables/slice_tables_py.h"
39 #include "src/trace_processor/tables/track_tables_py.h"
40
41 namespace perfetto::trace_processor {
42 namespace {
43
44 using SliceTable = tables::SliceTable;
45 using ThreadTrackTable = tables::ThreadTrackTable;
46 using ExpectedFrameTimelineSliceTable = tables::ExpectedFrameTimelineSliceTable;
47 using RawTable = tables::RawTable;
48 using FtraceEventTable = tables::FtraceEventTable;
49 using HeapGraphObjectTable = tables::HeapGraphObjectTable;
50
51 // `SELECT * FROM SLICE` on android_monitor_contention_trace.at
52 constexpr std::string_view kSliceTable =
53 "test/data/slice_table_for_benchmarks.csv";
54
55 // `SELECT * FROM SLICE` on android_monitor_contention_trace.at
56 constexpr std::string_view kExpectedFrameTimelineTable =
57 "test/data/expected_frame_timeline_for_benchmarks.csv";
58
59 // `SELECT id, cpu FROM raw` on chrome_android_systrace.pftrace.
60 constexpr std::string_view kRawTable = "test/data/raw_cpu_for_benchmarks.csv";
61
62 // `SELECT id, cpu FROM ftrace_event` on chrome_android_systrace.pftrace.
63 constexpr std::string_view kFtraceEventTable =
64 "test/data/ftrace_event_cpu_for_benchmarks.csv";
65
66 // `SELECT id, upid, reference_set_id FROM heap_graph_object` on
67 constexpr std::string_view kHeapGraphObjectTable =
68 "test/data/heap_pgraph_object_for_benchmarks_query.csv";
69
SplitCSVLine(const std::string & line)70 std::vector<std::string> SplitCSVLine(const std::string& line) {
71 std::vector<std::string> output;
72 uint32_t start = 0;
73 bool in_string = false;
74
75 for (uint32_t i = 0; i < line.size(); ++i) {
76 if (!in_string && line[i] == ',') {
77 output.emplace_back(&line[start], i - start);
78 start = i + 1;
79 continue;
80 }
81 if (line[i] == '"')
82 in_string = !in_string;
83 }
84
85 if (start < line.size())
86 output.emplace_back(&line[start], line.size() - start);
87
88 return output;
89 }
90
ReadCSV(benchmark::State & state,std::string_view file_name)91 std::vector<std::string> ReadCSV(benchmark::State& state,
92 std::string_view file_name) {
93 std::string table_csv;
94 perfetto::base::ReadFile(
95 perfetto::base::GetTestDataPath(std::string(file_name)), &table_csv);
96 if (table_csv.empty()) {
97 state.SkipWithError(
98 "Test strings missing. Googlers: download "
99 "go/perfetto-benchmark-trace-strings and save into /tmp/trace_strings");
100 return {};
101 }
102 PERFETTO_CHECK(!table_csv.empty());
103 return base::SplitString(table_csv, "\n");
104 }
105
106 template <typename It>
CountRows(It it)107 double CountRows(It it) {
108 double i = 0;
109 for (; it; ++it, ++i) {
110 }
111 return i;
112 }
113
StripAndIntern(StringPool & pool,const std::string & data)114 StringPool::Id StripAndIntern(StringPool& pool, const std::string& data) {
115 std::string res = base::StripSuffix(base::StripPrefix(data, "\""), "\"");
116 return pool.InternString(base::StringView(res));
117 }
118
GetSliceTableRow(const std::string & string_row,StringPool & pool)119 SliceTable::Row GetSliceTableRow(const std::string& string_row,
120 StringPool& pool) {
121 std::vector<std::string> row_vec = SplitCSVLine(string_row);
122 SliceTable::Row row;
123 PERFETTO_CHECK(row_vec.size() >= 14);
124 row.ts = *base::StringToInt64(row_vec[2]);
125 row.dur = *base::StringToInt64(row_vec[3]);
126 row.track_id = ThreadTrackTable::Id(*base::StringToUInt32(row_vec[4]));
127 row.category = StripAndIntern(pool, row_vec[5]);
128 row.name = StripAndIntern(pool, row_vec[6]);
129 row.depth = *base::StringToUInt32(row_vec[7]);
130 row.stack_id = *base::StringToInt32(row_vec[8]);
131 row.parent_stack_id = *base::StringToInt32(row_vec[9]);
132 row.parent_id = base::StringToUInt32(row_vec[10]).has_value()
133 ? std::make_optional<SliceTable::Id>(
134 *base::StringToUInt32(row_vec[10]))
135 : std::nullopt;
136 row.arg_set_id = *base::StringToUInt32(row_vec[11]);
137 row.thread_ts = base::StringToInt64(row_vec[12]);
138 row.thread_dur = base::StringToInt64(row_vec[13]);
139 return row;
140 }
141
142 struct SliceTableForBenchmark {
SliceTableForBenchmarkperfetto::trace_processor::__anon499c33ea0111::SliceTableForBenchmark143 explicit SliceTableForBenchmark(benchmark::State& state) : table_{&pool_} {
144 std::vector<std::string> rows_strings = ReadCSV(state, kSliceTable);
145
146 for (size_t i = 1; i < rows_strings.size(); ++i) {
147 table_.Insert(GetSliceTableRow(rows_strings[i], pool_));
148 }
149 }
150
151 StringPool pool_;
152 SliceTable table_;
153 };
154
155 struct ExpectedFrameTimelineTableForBenchmark {
ExpectedFrameTimelineTableForBenchmarkperfetto::trace_processor::__anon499c33ea0111::ExpectedFrameTimelineTableForBenchmark156 explicit ExpectedFrameTimelineTableForBenchmark(benchmark::State& state)
157 : table_{&pool_, &parent_} {
158 std::vector<std::string> table_rows_as_string =
159 ReadCSV(state, kExpectedFrameTimelineTable);
160 std::vector<std::string> parent_rows_as_string =
161 ReadCSV(state, kSliceTable);
162
163 uint32_t cur_idx = 0;
164 for (size_t i = 1; i < table_rows_as_string.size(); ++i, ++cur_idx) {
165 std::vector<std::string> row_vec = SplitCSVLine(table_rows_as_string[i]);
166
167 uint32_t idx = *base::StringToUInt32(row_vec[0]);
168 while (cur_idx < idx) {
169 parent_.Insert(
170 GetSliceTableRow(parent_rows_as_string[cur_idx + 1], pool_));
171 cur_idx++;
172 }
173
174 ExpectedFrameTimelineSliceTable::Row row;
175 row.ts = *base::StringToInt64(row_vec[2]);
176 row.dur = *base::StringToInt64(row_vec[3]);
177 row.track_id = ThreadTrackTable::Id(*base::StringToUInt32(row_vec[4]));
178 row.depth = *base::StringToUInt32(row_vec[7]);
179 row.stack_id = *base::StringToInt32(row_vec[8]);
180 row.parent_stack_id = *base::StringToInt32(row_vec[9]);
181 row.parent_id = base::StringToUInt32(row_vec[11]).has_value()
182 ? std::make_optional<SliceTable::Id>(
183 *base::StringToUInt32(row_vec[11]))
184 : std::nullopt;
185 row.arg_set_id = *base::StringToUInt32(row_vec[11]);
186 row.thread_ts = base::StringToInt64(row_vec[12]);
187 row.thread_dur = base::StringToInt64(row_vec[13]);
188 table_.Insert(row);
189 }
190 }
191 StringPool pool_;
192 SliceTable parent_{&pool_};
193 ExpectedFrameTimelineSliceTable table_;
194 };
195
196 struct FtraceEventTableForBenchmark {
FtraceEventTableForBenchmarkperfetto::trace_processor::__anon499c33ea0111::FtraceEventTableForBenchmark197 explicit FtraceEventTableForBenchmark(benchmark::State& state) {
198 std::vector<std::string> raw_rows = ReadCSV(state, kRawTable);
199 std::vector<std::string> ftrace_event_rows =
200 ReadCSV(state, kFtraceEventTable);
201
202 uint32_t cur_idx = 0;
203 for (size_t i = 1; i < ftrace_event_rows.size(); ++i, cur_idx++) {
204 std::vector<std::string> row_vec = SplitCSVLine(ftrace_event_rows[i]);
205 uint32_t idx = *base::StringToUInt32(row_vec[0]);
206 while (cur_idx < idx) {
207 std::vector<std::string> raw_row = SplitCSVLine(raw_rows[cur_idx + 1]);
208 RawTable::Row r;
209 r.ucpu = tables::CpuTable::Id(*base::StringToUInt32(raw_row[1]));
210 raw_.Insert(r);
211 cur_idx++;
212 }
213 FtraceEventTable::Row row;
214 row.ucpu = tables::CpuTable::Id(*base::StringToUInt32(row_vec[1]));
215 table_.Insert(row);
216 }
217 }
218
219 StringPool pool_;
220 RawTable raw_{&pool_};
221 tables::FtraceEventTable table_{&pool_, &raw_};
222 };
223
224 struct HeapGraphObjectTableForBenchmark {
HeapGraphObjectTableForBenchmarkperfetto::trace_processor::__anon499c33ea0111::HeapGraphObjectTableForBenchmark225 explicit HeapGraphObjectTableForBenchmark(benchmark::State& state) {
226 std::vector<std::string> table_rows_as_string =
227 ReadCSV(state, kHeapGraphObjectTable);
228
229 for (size_t i = 1; i < table_rows_as_string.size(); ++i) {
230 std::vector<std::string> row_vec = SplitCSVLine(table_rows_as_string[i]);
231
232 HeapGraphObjectTable::Row row;
233 row.upid = *base::StringToUInt32(row_vec[1]);
234 row.reference_set_id = base::StringToUInt32(row_vec[2]);
235 table_.Insert(row);
236 }
237 }
238 StringPool pool_;
239 HeapGraphObjectTable table_{&pool_};
240 };
241
BenchmarkSliceTableFilter(benchmark::State & state,SliceTableForBenchmark & table,std::initializer_list<Constraint> c)242 void BenchmarkSliceTableFilter(benchmark::State& state,
243 SliceTableForBenchmark& table,
244 std::initializer_list<Constraint> c) {
245 Query q;
246 q.constraints = c;
247 for (auto _ : state) {
248 benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
249 }
250 state.counters["s/row"] =
251 benchmark::Counter(static_cast<double>(table.table_.row_count()),
252 benchmark::Counter::kIsIterationInvariantRate |
253 benchmark::Counter::kInvert);
254 state.counters["s/out"] =
255 benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
256 benchmark::Counter::kIsIterationInvariantRate |
257 benchmark::Counter::kInvert);
258 }
259
BenchmarkSliceTableSort(benchmark::State & state,SliceTableForBenchmark & table,std::initializer_list<Order> ob)260 void BenchmarkSliceTableSort(benchmark::State& state,
261 SliceTableForBenchmark& table,
262 std::initializer_list<Order> ob) {
263 for (auto _ : state) {
264 benchmark::DoNotOptimize(table.table_.Sort(ob));
265 }
266 state.counters["s/row"] =
267 benchmark::Counter(static_cast<double>(table.table_.row_count()),
268 benchmark::Counter::kIsIterationInvariantRate |
269 benchmark::Counter::kInvert);
270 }
271
BenchmarkExpectedFrameTableQuery(benchmark::State & state,ExpectedFrameTimelineTableForBenchmark & table,Query q)272 void BenchmarkExpectedFrameTableQuery(
273 benchmark::State& state,
274 ExpectedFrameTimelineTableForBenchmark& table,
275 Query q) {
276 for (auto _ : state) {
277 benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
278 }
279 state.counters["s/row"] =
280 benchmark::Counter(static_cast<double>(table.table_.row_count()),
281 benchmark::Counter::kIsIterationInvariantRate |
282 benchmark::Counter::kInvert);
283 state.counters["s/out"] =
284 benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
285 benchmark::Counter::kIsIterationInvariantRate |
286 benchmark::Counter::kInvert);
287 }
288
BenchmarkFtraceEventTableQuery(benchmark::State & state,FtraceEventTableForBenchmark & table,Query q)289 void BenchmarkFtraceEventTableQuery(benchmark::State& state,
290 FtraceEventTableForBenchmark& table,
291 Query q) {
292 for (auto _ : state) {
293 benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
294 }
295 state.counters["s/row"] =
296 benchmark::Counter(static_cast<double>(table.table_.row_count()),
297 benchmark::Counter::kIsIterationInvariantRate |
298 benchmark::Counter::kInvert);
299 state.counters["s/out"] =
300 benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
301 benchmark::Counter::kIsIterationInvariantRate |
302 benchmark::Counter::kInvert);
303 }
304
BenchmarkFtraceEventTableSort(benchmark::State & state,FtraceEventTableForBenchmark & table,std::initializer_list<Order> ob)305 void BenchmarkFtraceEventTableSort(benchmark::State& state,
306 FtraceEventTableForBenchmark& table,
307 std::initializer_list<Order> ob) {
308 for (auto _ : state) {
309 benchmark::DoNotOptimize(table.table_.Sort(ob));
310 }
311 state.counters["s/row"] =
312 benchmark::Counter(static_cast<double>(table.table_.row_count()),
313 benchmark::Counter::kIsIterationInvariantRate |
314 benchmark::Counter::kInvert);
315 }
316
BM_QESliceTableTrackIdEq(benchmark::State & state)317 void BM_QESliceTableTrackIdEq(benchmark::State& state) {
318 SliceTableForBenchmark table(state);
319 BenchmarkSliceTableFilter(state, table, {table.table_.track_id().eq(1213)});
320 }
321 BENCHMARK(BM_QESliceTableTrackIdEq);
322
BM_QESliceTableParentIdIsNotNull(benchmark::State & state)323 void BM_QESliceTableParentIdIsNotNull(benchmark::State& state) {
324 SliceTableForBenchmark table(state);
325 BenchmarkSliceTableFilter(state, table,
326 {table.table_.parent_id().is_not_null()});
327 }
328 BENCHMARK(BM_QESliceTableParentIdIsNotNull);
329
BM_QESliceTableParentIdEq(benchmark::State & state)330 void BM_QESliceTableParentIdEq(benchmark::State& state) {
331 SliceTableForBenchmark table(state);
332 BenchmarkSliceTableFilter(state, table, {table.table_.parent_id().eq(26711)});
333 }
334 BENCHMARK(BM_QESliceTableParentIdEq);
335
BM_QESliceTableNameEq(benchmark::State & state)336 void BM_QESliceTableNameEq(benchmark::State& state) {
337 SliceTableForBenchmark table(state);
338 BenchmarkSliceTableFilter(
339 state, table,
340 {table.table_.name().eq("MarkFromReadBarrierWithMeasurements")});
341 }
342 BENCHMARK(BM_QESliceTableNameEq);
343
BM_QESliceTableNameGlobNoStars(benchmark::State & state)344 void BM_QESliceTableNameGlobNoStars(benchmark::State& state) {
345 SliceTableForBenchmark table(state);
346 BenchmarkSliceTableFilter(
347 state, table,
348 {table.table_.name().glob("MarkFromReadBarrierWithMeasurements")});
349 }
350 BENCHMARK(BM_QESliceTableNameGlobNoStars);
351
BM_QESliceTableNameGlob(benchmark::State & state)352 void BM_QESliceTableNameGlob(benchmark::State& state) {
353 SliceTableForBenchmark table(state);
354 BenchmarkSliceTableFilter(
355 state, table, {table.table_.name().glob("HIDL::IMapper::unlock::*")});
356 }
357 BENCHMARK(BM_QESliceTableNameGlob);
358
BM_QESliceTableNameRegex(benchmark::State & state)359 void BM_QESliceTableNameRegex(benchmark::State& state) {
360 SliceTableForBenchmark table(state);
361 BenchmarkSliceTableFilter(state, table,
362 {table.table_.name().regex(".*Pool.*")});
363 }
364 BENCHMARK(BM_QESliceTableNameRegex);
365
BM_QESliceTableSorted(benchmark::State & state)366 void BM_QESliceTableSorted(benchmark::State& state) {
367 SliceTableForBenchmark table(state);
368 BenchmarkSliceTableFilter(state, table,
369 {table.table_.ts().gt(1738923505854),
370 table.table_.ts().lt(1738950140556)});
371 }
372 BENCHMARK(BM_QESliceTableSorted);
373
BM_QEFilterWithSparseSelector(benchmark::State & state)374 void BM_QEFilterWithSparseSelector(benchmark::State& state) {
375 ExpectedFrameTimelineTableForBenchmark table(state);
376 Query q;
377 q.constraints = {table.table_.track_id().eq(1445)};
378 BenchmarkExpectedFrameTableQuery(state, table, q);
379 }
380 BENCHMARK(BM_QEFilterWithSparseSelector);
381
BM_QEFilterWithDenseSelector(benchmark::State & state)382 void BM_QEFilterWithDenseSelector(benchmark::State& state) {
383 FtraceEventTableForBenchmark table(state);
384 Query q;
385 q.constraints = {table.table_.ucpu().eq(4)};
386 BenchmarkFtraceEventTableQuery(state, table, q);
387 }
388 BENCHMARK(BM_QEFilterWithDenseSelector);
389
BM_QESliceEventFilterId(benchmark::State & state)390 void BM_QESliceEventFilterId(benchmark::State& state) {
391 SliceTableForBenchmark table(state);
392 BenchmarkSliceTableFilter(state, table, {table.table_.id().eq(500)});
393 }
394 BENCHMARK(BM_QESliceEventFilterId);
395
BM_QEFtraceEventFilterId(benchmark::State & state)396 void BM_QEFtraceEventFilterId(benchmark::State& state) {
397 FtraceEventTableForBenchmark table(state);
398 Query q;
399 q.constraints = {table.table_.id().eq(500)};
400 BenchmarkFtraceEventTableQuery(state, table, q);
401 }
402
403 BENCHMARK(BM_QEFtraceEventFilterId);
404
BM_QESliceTableTsAndTrackId(benchmark::State & state)405 void BM_QESliceTableTsAndTrackId(benchmark::State& state) {
406 SliceTableForBenchmark table(state);
407 BenchmarkSliceTableFilter(
408 state, table,
409 {table.table_.ts().ge(1738923505854), table.table_.ts().le(1738950140556),
410 table.table_.track_id().eq(1422)});
411 }
412 BENCHMARK(BM_QESliceTableTsAndTrackId);
413
BM_QEFilterOneElement(benchmark::State & state)414 void BM_QEFilterOneElement(benchmark::State& state) {
415 SliceTableForBenchmark table(state);
416 BenchmarkSliceTableFilter(
417 state, table,
418 {table.table_.id().eq(11732), table.table_.track_id().eq(1422)});
419 }
420 BENCHMARK(BM_QEFilterOneElement);
421
BM_QEFilterWithArrangement(benchmark::State & state)422 void BM_QEFilterWithArrangement(benchmark::State& state) {
423 SliceTableForBenchmark table(state);
424 Order order{table.table_.dur().index_in_table(), false};
425 Table slice_sorted_with_duration = table.table_.Sort({order});
426
427 Constraint c{table.table_.track_id().index_in_table(), FilterOp::kGt,
428 SqlValue::Long(10)};
429 Query q;
430 q.constraints = {c};
431 for (auto _ : state) {
432 benchmark::DoNotOptimize(slice_sorted_with_duration.QueryToRowMap(q));
433 }
434 state.counters["s/row"] = benchmark::Counter(
435 static_cast<double>(slice_sorted_with_duration.row_count()),
436 benchmark::Counter::kIsIterationInvariantRate |
437 benchmark::Counter::kInvert);
438 state.counters["s/out"] = benchmark::Counter(
439 static_cast<double>(table.table_.QueryToRowMap(q).size()),
440 benchmark::Counter::kIsIterationInvariantRate |
441 benchmark::Counter::kInvert);
442 }
443 BENCHMARK(BM_QEFilterWithArrangement);
444
BM_QEDenseNullFilter(benchmark::State & state)445 void BM_QEDenseNullFilter(benchmark::State& state) {
446 HeapGraphObjectTableForBenchmark table(state);
447 Constraint c{table.table_.reference_set_id().index_in_table(), FilterOp::kGt,
448 SqlValue::Long(1000)};
449 Query q;
450 q.constraints = {c};
451 for (auto _ : state) {
452 benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
453 }
454 state.counters["s/row"] =
455 benchmark::Counter(static_cast<double>(table.table_.row_count()),
456 benchmark::Counter::kIsIterationInvariantRate |
457 benchmark::Counter::kInvert);
458 state.counters["s/out"] =
459 benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
460 benchmark::Counter::kIsIterationInvariantRate |
461 benchmark::Counter::kInvert);
462 }
463 BENCHMARK(BM_QEDenseNullFilter);
464
BM_QEDenseNullFilterIsNull(benchmark::State & state)465 void BM_QEDenseNullFilterIsNull(benchmark::State& state) {
466 HeapGraphObjectTableForBenchmark table(state);
467 Constraint c{table.table_.reference_set_id().index_in_table(),
468 FilterOp::kIsNull, SqlValue()};
469 Query q;
470 q.constraints = {c};
471 for (auto _ : state) {
472 benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
473 }
474 state.counters["s/row"] =
475 benchmark::Counter(static_cast<double>(table.table_.row_count()),
476 benchmark::Counter::kIsIterationInvariantRate |
477 benchmark::Counter::kInvert);
478 state.counters["s/out"] =
479 benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
480 benchmark::Counter::kIsIterationInvariantRate |
481 benchmark::Counter::kInvert);
482 }
483 BENCHMARK(BM_QEDenseNullFilterIsNull);
484
BM_QEIdColumnWithIntAsDouble(benchmark::State & state)485 void BM_QEIdColumnWithIntAsDouble(benchmark::State& state) {
486 SliceTableForBenchmark table(state);
487 Constraint c{table.table_.track_id().index_in_table(), FilterOp::kEq,
488 SqlValue::Double(100)};
489 BenchmarkSliceTableFilter(state, table, {c});
490 }
491 BENCHMARK(BM_QEIdColumnWithIntAsDouble);
492
BM_QEIdColumnWithDouble(benchmark::State & state)493 void BM_QEIdColumnWithDouble(benchmark::State& state) {
494 SliceTableForBenchmark table(state);
495 Constraint c{table.table_.track_id().index_in_table(), FilterOp::kEq,
496 SqlValue::Double(100.5)};
497 BenchmarkSliceTableFilter(state, table, {c});
498 }
499 BENCHMARK(BM_QEIdColumnWithDouble);
500
BM_QEFilterOrderedArrangement(benchmark::State & state)501 void BM_QEFilterOrderedArrangement(benchmark::State& state) {
502 SliceTableForBenchmark table(state);
503 Order order{table.table_.dur().index_in_table(), false};
504 Table slice_sorted_with_duration = table.table_.Sort({order});
505
506 Constraint c{table.table_.dur().index_in_table(), FilterOp::kGt,
507 SqlValue::Long(10)};
508 Query q;
509 q.constraints = {c};
510 for (auto _ : state) {
511 benchmark::DoNotOptimize(slice_sorted_with_duration.QueryToRowMap(q));
512 }
513 state.counters["s/row"] = benchmark::Counter(
514 static_cast<double>(slice_sorted_with_duration.row_count()),
515 benchmark::Counter::kIsIterationInvariantRate |
516 benchmark::Counter::kInvert);
517 state.counters["s/out"] = benchmark::Counter(
518 static_cast<double>(table.table_.QueryToRowMap(q).size()),
519 benchmark::Counter::kIsIterationInvariantRate |
520 benchmark::Counter::kInvert);
521 }
522 BENCHMARK(BM_QEFilterOrderedArrangement);
523
BM_QEFilterNullOrderedArrangement(benchmark::State & state)524 void BM_QEFilterNullOrderedArrangement(benchmark::State& state) {
525 SliceTableForBenchmark table(state);
526 Order order{table.table_.parent_id().index_in_table(), false};
527 Table slice_sorted_with_parent_id = table.table_.Sort({order});
528
529 Constraint c{table.table_.parent_id().index_in_table(), FilterOp::kGt,
530 SqlValue::Long(26091)};
531 Query q;
532 q.constraints = {c};
533 for (auto _ : state) {
534 benchmark::DoNotOptimize(slice_sorted_with_parent_id.QueryToRowMap(q));
535 }
536 state.counters["s/row"] = benchmark::Counter(
537 static_cast<double>(slice_sorted_with_parent_id.row_count()),
538 benchmark::Counter::kIsIterationInvariantRate |
539 benchmark::Counter::kInvert);
540 state.counters["s/out"] = benchmark::Counter(
541 static_cast<double>(table.table_.QueryToRowMap(q).size()),
542 benchmark::Counter::kIsIterationInvariantRate |
543 benchmark::Counter::kInvert);
544 }
545 BENCHMARK(BM_QEFilterNullOrderedArrangement);
546
BM_QESliceFilterIndexSearchOneElement(benchmark::State & state)547 void BM_QESliceFilterIndexSearchOneElement(benchmark::State& state) {
548 SliceTableForBenchmark table(state);
549 BenchmarkSliceTableFilter(
550 state, table,
551 {table.table_.track_id().eq(1422), table.table_.id().eq(11732)});
552 }
553 BENCHMARK(BM_QESliceFilterIndexSearchOneElement);
554
BM_QESliceFilterIndexSearch(benchmark::State & state)555 void BM_QESliceFilterIndexSearch(benchmark::State& state) {
556 SliceTableForBenchmark table(state);
557 BenchmarkSliceTableFilter(state, table,
558 {table.table_.track_id().eq(1422),
559 table.table_.name().eq("notifyFramePending")});
560 }
561 BENCHMARK(BM_QESliceFilterIndexSearch);
562
BM_QESliceSortNumericAsc(benchmark::State & state)563 void BM_QESliceSortNumericAsc(benchmark::State& state) {
564 SliceTableForBenchmark table(state);
565 BenchmarkSliceTableSort(state, table, {table.table_.track_id().ascending()});
566 }
567 BENCHMARK(BM_QESliceSortNumericAsc);
568
BM_QESliceSortNullNumericAsc(benchmark::State & state)569 void BM_QESliceSortNullNumericAsc(benchmark::State& state) {
570 SliceTableForBenchmark table(state);
571 BenchmarkSliceTableSort(state, table, {table.table_.parent_id().ascending()});
572 }
573 BENCHMARK(BM_QESliceSortNullNumericAsc);
574
BM_QEFtraceEventSortSelectorNumericAsc(benchmark::State & state)575 void BM_QEFtraceEventSortSelectorNumericAsc(benchmark::State& state) {
576 FtraceEventTableForBenchmark table(state);
577 BenchmarkFtraceEventTableSort(state, table,
578 {table.table_.ucpu().ascending()});
579 }
580 BENCHMARK(BM_QEFtraceEventSortSelectorNumericAsc);
581
BM_QEFtraceEventSortSelectorNumericDesc(benchmark::State & state)582 void BM_QEFtraceEventSortSelectorNumericDesc(benchmark::State& state) {
583 FtraceEventTableForBenchmark table(state);
584 BenchmarkFtraceEventTableSort(state, table,
585 {table.table_.ucpu().descending()});
586 }
587 BENCHMARK(BM_QEFtraceEventSortSelectorNumericDesc);
588
BM_QEDistinctWithSparseSelector(benchmark::State & state)589 void BM_QEDistinctWithSparseSelector(benchmark::State& state) {
590 ExpectedFrameTimelineTableForBenchmark table(state);
591 Query q;
592 q.order_type = Query::OrderType::kDistinct;
593 q.orders = {table.table_.track_id().descending()};
594 BenchmarkExpectedFrameTableQuery(state, table, q);
595 }
596 BENCHMARK(BM_QEDistinctWithSparseSelector);
597
BM_QEDistinctWithDenseSelector(benchmark::State & state)598 void BM_QEDistinctWithDenseSelector(benchmark::State& state) {
599 FtraceEventTableForBenchmark table(state);
600 Query q;
601 q.order_type = Query::OrderType::kDistinct;
602 q.orders = {table.table_.ucpu().descending()};
603 BenchmarkFtraceEventTableQuery(state, table, q);
604 }
605 BENCHMARK(BM_QEDistinctWithDenseSelector);
606
BM_QEDistinctSortedWithSparseSelector(benchmark::State & state)607 void BM_QEDistinctSortedWithSparseSelector(benchmark::State& state) {
608 ExpectedFrameTimelineTableForBenchmark table(state);
609 Query q;
610 q.order_type = Query::OrderType::kDistinctAndSort;
611 q.orders = {table.table_.track_id().descending()};
612 BenchmarkExpectedFrameTableQuery(state, table, q);
613 }
614 BENCHMARK(BM_QEDistinctSortedWithSparseSelector);
615
BM_QEDistinctSortedWithDenseSelector(benchmark::State & state)616 void BM_QEDistinctSortedWithDenseSelector(benchmark::State& state) {
617 FtraceEventTableForBenchmark table(state);
618 Query q;
619 q.order_type = Query::OrderType::kDistinctAndSort;
620 q.orders = {table.table_.ucpu().descending()};
621 BenchmarkFtraceEventTableQuery(state, table, q);
622 }
623 BENCHMARK(BM_QEDistinctSortedWithDenseSelector);
624
BM_QEDistinctWithArrangement(benchmark::State & state)625 void BM_QEDistinctWithArrangement(benchmark::State& state) {
626 SliceTableForBenchmark table(state);
627 Order order{table.table_.dur().index_in_table(), false};
628 Table slice_sorted_with_duration = table.table_.Sort({order});
629
630 Query q;
631 q.order_type = Query::OrderType::kDistinct;
632 q.orders = {table.table_.track_id().descending()};
633
634 for (auto _ : state) {
635 benchmark::DoNotOptimize(slice_sorted_with_duration.QueryToRowMap(q));
636 }
637 state.counters["s/row"] = benchmark::Counter(
638 static_cast<double>(slice_sorted_with_duration.row_count()),
639 benchmark::Counter::kIsIterationInvariantRate |
640 benchmark::Counter::kInvert);
641 state.counters["s/out"] = benchmark::Counter(
642 static_cast<double>(table.table_.QueryToRowMap(q).size()),
643 benchmark::Counter::kIsIterationInvariantRate |
644 benchmark::Counter::kInvert);
645 }
646 BENCHMARK(BM_QEDistinctWithArrangement);
647
BM_QEDistinctSortedWithArrangement(benchmark::State & state)648 void BM_QEDistinctSortedWithArrangement(benchmark::State& state) {
649 SliceTableForBenchmark table(state);
650 Order order{table.table_.dur().index_in_table(), false};
651 Table slice_sorted_with_duration = table.table_.Sort({order});
652
653 Query q;
654 q.order_type = Query::OrderType::kDistinctAndSort;
655 q.orders = {table.table_.track_id().descending()};
656
657 for (auto _ : state) {
658 benchmark::DoNotOptimize(slice_sorted_with_duration.QueryToRowMap(q));
659 }
660 state.counters["s/row"] = benchmark::Counter(
661 static_cast<double>(slice_sorted_with_duration.row_count()),
662 benchmark::Counter::kIsIterationInvariantRate |
663 benchmark::Counter::kInvert);
664 state.counters["s/out"] = benchmark::Counter(
665 static_cast<double>(table.table_.QueryToRowMap(q).size()),
666 benchmark::Counter::kIsIterationInvariantRate |
667 benchmark::Counter::kInvert);
668 }
669 BENCHMARK(BM_QEDistinctSortedWithArrangement);
670
BM_QEOffsetLimit(benchmark::State & state)671 void BM_QEOffsetLimit(benchmark::State& state) {
672 FtraceEventTableForBenchmark table(state);
673 Query q;
674 q.limit = 10;
675 q.offset = 100;
676 BenchmarkFtraceEventTableQuery(state, table, q);
677 }
678 BENCHMARK(BM_QEOffsetLimit);
679
BM_QEMax(benchmark::State & state)680 void BM_QEMax(benchmark::State& state) {
681 FtraceEventTableForBenchmark table(state);
682 Query q;
683 q.limit = 1;
684 q.orders = {table.table_.utid().descending()};
685 BenchmarkFtraceEventTableQuery(state, table, q);
686 }
687 BENCHMARK(BM_QEMax);
688
689 } // namespace
690 } // namespace perfetto::trace_processor
691