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 FtraceEventTable = tables::FtraceEventTable;
46 using HeapGraphObjectTable = tables::HeapGraphObjectTable;
47
48 // `SELECT * FROM SLICE` on android_monitor_contention_trace.at
49 constexpr std::string_view kSliceTable =
50 "test/data/slice_table_for_benchmarks.csv";
51
52 // `SELECT id, cpu FROM raw` on chrome_android_systrace.pftrace.
53 constexpr std::string_view kRawTable = "test/data/raw_cpu_for_benchmarks.csv";
54
55 // `SELECT id, cpu FROM ftrace_event` on chrome_android_systrace.pftrace.
56 constexpr std::string_view kFtraceEventTable =
57 "test/data/ftrace_event_cpu_for_benchmarks.csv";
58
59 // `SELECT id, upid, reference_set_id FROM heap_graph_object` on
60 constexpr std::string_view kHeapGraphObjectTable =
61 "test/data/heap_pgraph_object_for_benchmarks_query.csv";
62
SplitCSVLine(const std::string & line)63 std::vector<std::string> SplitCSVLine(const std::string& line) {
64 std::vector<std::string> output;
65 uint32_t start = 0;
66 bool in_string = false;
67
68 for (uint32_t i = 0; i < line.size(); ++i) {
69 if (!in_string && line[i] == ',') {
70 output.emplace_back(&line[start], i - start);
71 start = i + 1;
72 continue;
73 }
74 if (line[i] == '"')
75 in_string = !in_string;
76 }
77
78 if (start < line.size())
79 output.emplace_back(&line[start], line.size() - start);
80
81 return output;
82 }
83
ReadCSV(benchmark::State & state,std::string_view file_name)84 std::vector<std::string> ReadCSV(benchmark::State& state,
85 std::string_view file_name) {
86 std::string table_csv;
87 perfetto::base::ReadFile(
88 perfetto::base::GetTestDataPath(std::string(file_name)), &table_csv);
89 if (table_csv.empty()) {
90 state.SkipWithError(
91 "Test strings missing. Googlers: download "
92 "go/perfetto-benchmark-trace-strings and save into /tmp/trace_strings");
93 return {};
94 }
95 PERFETTO_CHECK(!table_csv.empty());
96 return base::SplitString(table_csv, "\n");
97 }
98
99 template <typename It>
CountRows(It it)100 double CountRows(It it) {
101 double i = 0;
102 for (; it; ++it, ++i) {
103 }
104 return i;
105 }
106
StripAndIntern(StringPool & pool,const std::string & data)107 StringPool::Id StripAndIntern(StringPool& pool, const std::string& data) {
108 std::string res = base::StripSuffix(base::StripPrefix(data, "\""), "\"");
109 return pool.InternString(base::StringView(res));
110 }
111
GetSliceTableRow(const std::string & string_row,StringPool & pool)112 SliceTable::Row GetSliceTableRow(const std::string& string_row,
113 StringPool& pool) {
114 std::vector<std::string> row_vec = SplitCSVLine(string_row);
115 SliceTable::Row row;
116 PERFETTO_CHECK(row_vec.size() >= 14);
117 row.ts = *base::StringToInt64(row_vec[2]);
118 row.dur = *base::StringToInt64(row_vec[3]);
119 row.track_id = tables::TrackTable::Id(*base::StringToUInt32(row_vec[4]));
120 row.category = StripAndIntern(pool, row_vec[5]);
121 row.name = StripAndIntern(pool, row_vec[6]);
122 row.depth = *base::StringToUInt32(row_vec[7]);
123 row.stack_id = *base::StringToInt32(row_vec[8]);
124 row.parent_stack_id = *base::StringToInt32(row_vec[9]);
125 row.parent_id = base::StringToUInt32(row_vec[10]).has_value()
126 ? std::make_optional<SliceTable::Id>(
127 *base::StringToUInt32(row_vec[10]))
128 : std::nullopt;
129 row.arg_set_id = *base::StringToUInt32(row_vec[11]);
130 row.thread_ts = base::StringToInt64(row_vec[12]);
131 row.thread_dur = base::StringToInt64(row_vec[13]);
132 return row;
133 }
134
135 struct SliceTableForBenchmark {
SliceTableForBenchmarkperfetto::trace_processor::__anonc1c48e6a0111::SliceTableForBenchmark136 explicit SliceTableForBenchmark(benchmark::State& state) : table_{&pool_} {
137 std::vector<std::string> rows_strings = ReadCSV(state, kSliceTable);
138
139 for (size_t i = 1; i < rows_strings.size(); ++i) {
140 table_.Insert(GetSliceTableRow(rows_strings[i], pool_));
141 }
142 }
143
144 StringPool pool_;
145 SliceTable table_;
146 };
147
148 struct FtraceEventTableForBenchmark {
FtraceEventTableForBenchmarkperfetto::trace_processor::__anonc1c48e6a0111::FtraceEventTableForBenchmark149 explicit FtraceEventTableForBenchmark(benchmark::State& state) {
150 std::vector<std::string> raw_rows = ReadCSV(state, kRawTable);
151 std::vector<std::string> ftrace_event_rows =
152 ReadCSV(state, kFtraceEventTable);
153
154 uint32_t cur_idx = 0;
155 for (size_t i = 1; i < ftrace_event_rows.size(); ++i, cur_idx++) {
156 std::vector<std::string> row_vec = SplitCSVLine(ftrace_event_rows[i]);
157 FtraceEventTable::Row row;
158 row.ucpu = tables::CpuTable::Id(*base::StringToUInt32(row_vec[1]));
159 table_.Insert(row);
160 }
161 }
162
163 StringPool pool_;
164 tables::FtraceEventTable table_{&pool_};
165 };
166
167 struct HeapGraphObjectTableForBenchmark {
HeapGraphObjectTableForBenchmarkperfetto::trace_processor::__anonc1c48e6a0111::HeapGraphObjectTableForBenchmark168 explicit HeapGraphObjectTableForBenchmark(benchmark::State& state) {
169 std::vector<std::string> table_rows_as_string =
170 ReadCSV(state, kHeapGraphObjectTable);
171
172 for (size_t i = 1; i < table_rows_as_string.size(); ++i) {
173 std::vector<std::string> row_vec = SplitCSVLine(table_rows_as_string[i]);
174
175 HeapGraphObjectTable::Row row;
176 row.upid = *base::StringToUInt32(row_vec[1]);
177 row.reference_set_id = base::StringToUInt32(row_vec[2]);
178 table_.Insert(row);
179 }
180 }
181 StringPool pool_;
182 HeapGraphObjectTable table_{&pool_};
183 };
184
BenchmarkSliceTableFilter(benchmark::State & state,SliceTableForBenchmark & table,std::initializer_list<Constraint> c)185 void BenchmarkSliceTableFilter(benchmark::State& state,
186 SliceTableForBenchmark& table,
187 std::initializer_list<Constraint> c) {
188 Query q;
189 q.constraints = c;
190 for (auto _ : state) {
191 benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
192 }
193 state.counters["s/row"] =
194 benchmark::Counter(static_cast<double>(table.table_.row_count()),
195 benchmark::Counter::kIsIterationInvariantRate |
196 benchmark::Counter::kInvert);
197 state.counters["s/out"] =
198 benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
199 benchmark::Counter::kIsIterationInvariantRate |
200 benchmark::Counter::kInvert);
201 }
202
BenchmarkSliceTableSort(benchmark::State & state,SliceTableForBenchmark & table,std::initializer_list<Order> ob)203 void BenchmarkSliceTableSort(benchmark::State& state,
204 SliceTableForBenchmark& table,
205 std::initializer_list<Order> ob) {
206 for (auto _ : state) {
207 benchmark::DoNotOptimize(table.table_.Sort(ob));
208 }
209 state.counters["s/row"] =
210 benchmark::Counter(static_cast<double>(table.table_.row_count()),
211 benchmark::Counter::kIsIterationInvariantRate |
212 benchmark::Counter::kInvert);
213 }
214
BenchmarkFtraceEventTableQuery(benchmark::State & state,FtraceEventTableForBenchmark & table,Query q)215 void BenchmarkFtraceEventTableQuery(benchmark::State& state,
216 FtraceEventTableForBenchmark& table,
217 Query q) {
218 for (auto _ : state) {
219 benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
220 }
221 state.counters["s/row"] =
222 benchmark::Counter(static_cast<double>(table.table_.row_count()),
223 benchmark::Counter::kIsIterationInvariantRate |
224 benchmark::Counter::kInvert);
225 state.counters["s/out"] =
226 benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
227 benchmark::Counter::kIsIterationInvariantRate |
228 benchmark::Counter::kInvert);
229 }
230
BenchmarkFtraceEventTableSort(benchmark::State & state,FtraceEventTableForBenchmark & table,std::initializer_list<Order> ob)231 void BenchmarkFtraceEventTableSort(benchmark::State& state,
232 FtraceEventTableForBenchmark& table,
233 std::initializer_list<Order> ob) {
234 for (auto _ : state) {
235 benchmark::DoNotOptimize(table.table_.Sort(ob));
236 }
237 state.counters["s/row"] =
238 benchmark::Counter(static_cast<double>(table.table_.row_count()),
239 benchmark::Counter::kIsIterationInvariantRate |
240 benchmark::Counter::kInvert);
241 }
242
BM_QESliceTableTrackIdEq(benchmark::State & state)243 void BM_QESliceTableTrackIdEq(benchmark::State& state) {
244 SliceTableForBenchmark table(state);
245 BenchmarkSliceTableFilter(state, table, {table.table_.track_id().eq(1213)});
246 }
247 BENCHMARK(BM_QESliceTableTrackIdEq);
248
BM_QESliceTableParentIdIsNotNull(benchmark::State & state)249 void BM_QESliceTableParentIdIsNotNull(benchmark::State& state) {
250 SliceTableForBenchmark table(state);
251 BenchmarkSliceTableFilter(state, table,
252 {table.table_.parent_id().is_not_null()});
253 }
254 BENCHMARK(BM_QESliceTableParentIdIsNotNull);
255
BM_QESliceTableParentIdEq(benchmark::State & state)256 void BM_QESliceTableParentIdEq(benchmark::State& state) {
257 SliceTableForBenchmark table(state);
258 BenchmarkSliceTableFilter(state, table, {table.table_.parent_id().eq(26711)});
259 }
260 BENCHMARK(BM_QESliceTableParentIdEq);
261
BM_QESliceTableNameEq(benchmark::State & state)262 void BM_QESliceTableNameEq(benchmark::State& state) {
263 SliceTableForBenchmark table(state);
264 BenchmarkSliceTableFilter(
265 state, table,
266 {table.table_.name().eq("MarkFromReadBarrierWithMeasurements")});
267 }
268 BENCHMARK(BM_QESliceTableNameEq);
269
BM_QESliceTableNameGlobNoStars(benchmark::State & state)270 void BM_QESliceTableNameGlobNoStars(benchmark::State& state) {
271 SliceTableForBenchmark table(state);
272 BenchmarkSliceTableFilter(
273 state, table,
274 {table.table_.name().glob("MarkFromReadBarrierWithMeasurements")});
275 }
276 BENCHMARK(BM_QESliceTableNameGlobNoStars);
277
BM_QESliceTableNameGlob(benchmark::State & state)278 void BM_QESliceTableNameGlob(benchmark::State& state) {
279 SliceTableForBenchmark table(state);
280 BenchmarkSliceTableFilter(
281 state, table, {table.table_.name().glob("HIDL::IMapper::unlock::*")});
282 }
283 BENCHMARK(BM_QESliceTableNameGlob);
284
BM_QESliceTableNameRegex(benchmark::State & state)285 void BM_QESliceTableNameRegex(benchmark::State& state) {
286 SliceTableForBenchmark table(state);
287 BenchmarkSliceTableFilter(state, table,
288 {table.table_.name().regex(".*Pool.*")});
289 }
290 BENCHMARK(BM_QESliceTableNameRegex);
291
BM_QESliceTableSorted(benchmark::State & state)292 void BM_QESliceTableSorted(benchmark::State& state) {
293 SliceTableForBenchmark table(state);
294 BenchmarkSliceTableFilter(state, table,
295 {table.table_.ts().gt(1738923505854),
296 table.table_.ts().lt(1738950140556)});
297 }
298 BENCHMARK(BM_QESliceTableSorted);
299
BM_QEFilterWithDenseSelector(benchmark::State & state)300 void BM_QEFilterWithDenseSelector(benchmark::State& state) {
301 FtraceEventTableForBenchmark table(state);
302 Query q;
303 q.constraints = {table.table_.ucpu().eq(4)};
304 BenchmarkFtraceEventTableQuery(state, table, q);
305 }
306 BENCHMARK(BM_QEFilterWithDenseSelector);
307
BM_QESliceEventFilterId(benchmark::State & state)308 void BM_QESliceEventFilterId(benchmark::State& state) {
309 SliceTableForBenchmark table(state);
310 BenchmarkSliceTableFilter(state, table, {table.table_.id().eq(500)});
311 }
312 BENCHMARK(BM_QESliceEventFilterId);
313
BM_QEFtraceEventFilterId(benchmark::State & state)314 void BM_QEFtraceEventFilterId(benchmark::State& state) {
315 FtraceEventTableForBenchmark table(state);
316 Query q;
317 q.constraints = {table.table_.id().eq(500)};
318 BenchmarkFtraceEventTableQuery(state, table, q);
319 }
320
321 BENCHMARK(BM_QEFtraceEventFilterId);
322
BM_QESliceTableTsAndTrackId(benchmark::State & state)323 void BM_QESliceTableTsAndTrackId(benchmark::State& state) {
324 SliceTableForBenchmark table(state);
325 BenchmarkSliceTableFilter(
326 state, table,
327 {table.table_.ts().ge(1738923505854), table.table_.ts().le(1738950140556),
328 table.table_.track_id().eq(1422)});
329 }
330 BENCHMARK(BM_QESliceTableTsAndTrackId);
331
BM_QEFilterOneElement(benchmark::State & state)332 void BM_QEFilterOneElement(benchmark::State& state) {
333 SliceTableForBenchmark table(state);
334 BenchmarkSliceTableFilter(
335 state, table,
336 {table.table_.id().eq(11732), table.table_.track_id().eq(1422)});
337 }
338 BENCHMARK(BM_QEFilterOneElement);
339
BM_QEFilterWithArrangement(benchmark::State & state)340 void BM_QEFilterWithArrangement(benchmark::State& state) {
341 SliceTableForBenchmark table(state);
342 Order order{table.table_.dur().index_in_table(), false};
343 Table slice_sorted_with_duration = table.table_.Sort({order});
344
345 Constraint c{table.table_.track_id().index_in_table(), FilterOp::kGt,
346 SqlValue::Long(10)};
347 Query q;
348 q.constraints = {c};
349 for (auto _ : state) {
350 benchmark::DoNotOptimize(slice_sorted_with_duration.QueryToRowMap(q));
351 }
352 state.counters["s/row"] = benchmark::Counter(
353 static_cast<double>(slice_sorted_with_duration.row_count()),
354 benchmark::Counter::kIsIterationInvariantRate |
355 benchmark::Counter::kInvert);
356 state.counters["s/out"] = benchmark::Counter(
357 static_cast<double>(table.table_.QueryToRowMap(q).size()),
358 benchmark::Counter::kIsIterationInvariantRate |
359 benchmark::Counter::kInvert);
360 }
361 BENCHMARK(BM_QEFilterWithArrangement);
362
BM_QEDenseNullFilter(benchmark::State & state)363 void BM_QEDenseNullFilter(benchmark::State& state) {
364 HeapGraphObjectTableForBenchmark table(state);
365 Constraint c{table.table_.reference_set_id().index_in_table(), FilterOp::kGt,
366 SqlValue::Long(1000)};
367 Query q;
368 q.constraints = {c};
369 for (auto _ : state) {
370 benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
371 }
372 state.counters["s/row"] =
373 benchmark::Counter(static_cast<double>(table.table_.row_count()),
374 benchmark::Counter::kIsIterationInvariantRate |
375 benchmark::Counter::kInvert);
376 state.counters["s/out"] =
377 benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
378 benchmark::Counter::kIsIterationInvariantRate |
379 benchmark::Counter::kInvert);
380 }
381 BENCHMARK(BM_QEDenseNullFilter);
382
BM_QEDenseNullFilterIsNull(benchmark::State & state)383 void BM_QEDenseNullFilterIsNull(benchmark::State& state) {
384 HeapGraphObjectTableForBenchmark table(state);
385 Constraint c{table.table_.reference_set_id().index_in_table(),
386 FilterOp::kIsNull, SqlValue()};
387 Query q;
388 q.constraints = {c};
389 for (auto _ : state) {
390 benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
391 }
392 state.counters["s/row"] =
393 benchmark::Counter(static_cast<double>(table.table_.row_count()),
394 benchmark::Counter::kIsIterationInvariantRate |
395 benchmark::Counter::kInvert);
396 state.counters["s/out"] =
397 benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
398 benchmark::Counter::kIsIterationInvariantRate |
399 benchmark::Counter::kInvert);
400 }
401 BENCHMARK(BM_QEDenseNullFilterIsNull);
402
BM_QEIdColumnWithIntAsDouble(benchmark::State & state)403 void BM_QEIdColumnWithIntAsDouble(benchmark::State& state) {
404 SliceTableForBenchmark table(state);
405 Constraint c{table.table_.track_id().index_in_table(), FilterOp::kEq,
406 SqlValue::Double(100)};
407 BenchmarkSliceTableFilter(state, table, {c});
408 }
409 BENCHMARK(BM_QEIdColumnWithIntAsDouble);
410
BM_QEIdColumnWithDouble(benchmark::State & state)411 void BM_QEIdColumnWithDouble(benchmark::State& state) {
412 SliceTableForBenchmark table(state);
413 Constraint c{table.table_.track_id().index_in_table(), FilterOp::kEq,
414 SqlValue::Double(100.5)};
415 BenchmarkSliceTableFilter(state, table, {c});
416 }
417 BENCHMARK(BM_QEIdColumnWithDouble);
418
BM_QEFilterOrderedArrangement(benchmark::State & state)419 void BM_QEFilterOrderedArrangement(benchmark::State& state) {
420 SliceTableForBenchmark table(state);
421 Order order{table.table_.dur().index_in_table(), false};
422 Table slice_sorted_with_duration = table.table_.Sort({order});
423
424 Constraint c{table.table_.dur().index_in_table(), FilterOp::kGt,
425 SqlValue::Long(10)};
426 Query q;
427 q.constraints = {c};
428 for (auto _ : state) {
429 benchmark::DoNotOptimize(slice_sorted_with_duration.QueryToRowMap(q));
430 }
431 state.counters["s/row"] = benchmark::Counter(
432 static_cast<double>(slice_sorted_with_duration.row_count()),
433 benchmark::Counter::kIsIterationInvariantRate |
434 benchmark::Counter::kInvert);
435 state.counters["s/out"] = benchmark::Counter(
436 static_cast<double>(table.table_.QueryToRowMap(q).size()),
437 benchmark::Counter::kIsIterationInvariantRate |
438 benchmark::Counter::kInvert);
439 }
440 BENCHMARK(BM_QEFilterOrderedArrangement);
441
BM_QEFilterNullOrderedArrangement(benchmark::State & state)442 void BM_QEFilterNullOrderedArrangement(benchmark::State& state) {
443 SliceTableForBenchmark table(state);
444 Order order{table.table_.parent_id().index_in_table(), false};
445 Table slice_sorted_with_parent_id = table.table_.Sort({order});
446
447 Constraint c{table.table_.parent_id().index_in_table(), FilterOp::kGt,
448 SqlValue::Long(26091)};
449 Query q;
450 q.constraints = {c};
451 for (auto _ : state) {
452 benchmark::DoNotOptimize(slice_sorted_with_parent_id.QueryToRowMap(q));
453 }
454 state.counters["s/row"] = benchmark::Counter(
455 static_cast<double>(slice_sorted_with_parent_id.row_count()),
456 benchmark::Counter::kIsIterationInvariantRate |
457 benchmark::Counter::kInvert);
458 state.counters["s/out"] = benchmark::Counter(
459 static_cast<double>(table.table_.QueryToRowMap(q).size()),
460 benchmark::Counter::kIsIterationInvariantRate |
461 benchmark::Counter::kInvert);
462 }
463 BENCHMARK(BM_QEFilterNullOrderedArrangement);
464
BM_QESliceFilterIndexSearchOneElement(benchmark::State & state)465 void BM_QESliceFilterIndexSearchOneElement(benchmark::State& state) {
466 SliceTableForBenchmark table(state);
467 BenchmarkSliceTableFilter(
468 state, table,
469 {table.table_.track_id().eq(1422), table.table_.id().eq(11732)});
470 }
471 BENCHMARK(BM_QESliceFilterIndexSearchOneElement);
472
BM_QESliceFilterIndexSearch(benchmark::State & state)473 void BM_QESliceFilterIndexSearch(benchmark::State& state) {
474 SliceTableForBenchmark table(state);
475 BenchmarkSliceTableFilter(state, table,
476 {table.table_.track_id().eq(1422),
477 table.table_.name().eq("notifyFramePending")});
478 }
479 BENCHMARK(BM_QESliceFilterIndexSearch);
480
BM_QESliceSortNumericAsc(benchmark::State & state)481 void BM_QESliceSortNumericAsc(benchmark::State& state) {
482 SliceTableForBenchmark table(state);
483 BenchmarkSliceTableSort(state, table, {table.table_.track_id().ascending()});
484 }
485 BENCHMARK(BM_QESliceSortNumericAsc);
486
BM_QESliceSortNullNumericAsc(benchmark::State & state)487 void BM_QESliceSortNullNumericAsc(benchmark::State& state) {
488 SliceTableForBenchmark table(state);
489 BenchmarkSliceTableSort(state, table, {table.table_.parent_id().ascending()});
490 }
491 BENCHMARK(BM_QESliceSortNullNumericAsc);
492
BM_QEFtraceEventSortSelectorNumericAsc(benchmark::State & state)493 void BM_QEFtraceEventSortSelectorNumericAsc(benchmark::State& state) {
494 FtraceEventTableForBenchmark table(state);
495 BenchmarkFtraceEventTableSort(state, table,
496 {table.table_.ucpu().ascending()});
497 }
498 BENCHMARK(BM_QEFtraceEventSortSelectorNumericAsc);
499
BM_QEFtraceEventSortSelectorNumericDesc(benchmark::State & state)500 void BM_QEFtraceEventSortSelectorNumericDesc(benchmark::State& state) {
501 FtraceEventTableForBenchmark table(state);
502 BenchmarkFtraceEventTableSort(state, table,
503 {table.table_.ucpu().descending()});
504 }
505 BENCHMARK(BM_QEFtraceEventSortSelectorNumericDesc);
506
BM_QEDistinctWithDenseSelector(benchmark::State & state)507 void BM_QEDistinctWithDenseSelector(benchmark::State& state) {
508 FtraceEventTableForBenchmark table(state);
509 Query q;
510 q.order_type = Query::OrderType::kDistinct;
511 q.orders = {table.table_.ucpu().descending()};
512 BenchmarkFtraceEventTableQuery(state, table, q);
513 }
514 BENCHMARK(BM_QEDistinctWithDenseSelector);
515
BM_QEDistinctSortedWithDenseSelector(benchmark::State & state)516 void BM_QEDistinctSortedWithDenseSelector(benchmark::State& state) {
517 FtraceEventTableForBenchmark table(state);
518 Query q;
519 q.order_type = Query::OrderType::kDistinctAndSort;
520 q.orders = {table.table_.ucpu().descending()};
521 BenchmarkFtraceEventTableQuery(state, table, q);
522 }
523 BENCHMARK(BM_QEDistinctSortedWithDenseSelector);
524
BM_QEDistinctWithArrangement(benchmark::State & state)525 void BM_QEDistinctWithArrangement(benchmark::State& state) {
526 SliceTableForBenchmark table(state);
527 Order order{table.table_.dur().index_in_table(), false};
528 Table slice_sorted_with_duration = table.table_.Sort({order});
529
530 Query q;
531 q.order_type = Query::OrderType::kDistinct;
532 q.orders = {table.table_.track_id().descending()};
533
534 for (auto _ : state) {
535 benchmark::DoNotOptimize(slice_sorted_with_duration.QueryToRowMap(q));
536 }
537 state.counters["s/row"] = benchmark::Counter(
538 static_cast<double>(slice_sorted_with_duration.row_count()),
539 benchmark::Counter::kIsIterationInvariantRate |
540 benchmark::Counter::kInvert);
541 state.counters["s/out"] = benchmark::Counter(
542 static_cast<double>(table.table_.QueryToRowMap(q).size()),
543 benchmark::Counter::kIsIterationInvariantRate |
544 benchmark::Counter::kInvert);
545 }
546 BENCHMARK(BM_QEDistinctWithArrangement);
547
BM_QEDistinctSortedWithArrangement(benchmark::State & state)548 void BM_QEDistinctSortedWithArrangement(benchmark::State& state) {
549 SliceTableForBenchmark table(state);
550 Order order{table.table_.dur().index_in_table(), false};
551 Table slice_sorted_with_duration = table.table_.Sort({order});
552
553 Query q;
554 q.order_type = Query::OrderType::kDistinctAndSort;
555 q.orders = {table.table_.track_id().descending()};
556
557 for (auto _ : state) {
558 benchmark::DoNotOptimize(slice_sorted_with_duration.QueryToRowMap(q));
559 }
560 state.counters["s/row"] = benchmark::Counter(
561 static_cast<double>(slice_sorted_with_duration.row_count()),
562 benchmark::Counter::kIsIterationInvariantRate |
563 benchmark::Counter::kInvert);
564 state.counters["s/out"] = benchmark::Counter(
565 static_cast<double>(table.table_.QueryToRowMap(q).size()),
566 benchmark::Counter::kIsIterationInvariantRate |
567 benchmark::Counter::kInvert);
568 }
569 BENCHMARK(BM_QEDistinctSortedWithArrangement);
570
BM_QEOffsetLimit(benchmark::State & state)571 void BM_QEOffsetLimit(benchmark::State& state) {
572 FtraceEventTableForBenchmark table(state);
573 Query q;
574 q.limit = 10;
575 q.offset = 100;
576 BenchmarkFtraceEventTableQuery(state, table, q);
577 }
578 BENCHMARK(BM_QEOffsetLimit);
579
BM_QEMax(benchmark::State & state)580 void BM_QEMax(benchmark::State& state) {
581 FtraceEventTableForBenchmark table(state);
582 Query q;
583 q.limit = 1;
584 q.orders = {table.table_.utid().descending()};
585 BenchmarkFtraceEventTableQuery(state, table, q);
586 }
587 BENCHMARK(BM_QEMax);
588
589 } // namespace
590 } // namespace perfetto::trace_processor
591