• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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