xref: /aosp_15_r20/external/perfetto/src/kallsyms/kernel_symbol_map_benchmark.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <random>
16 #include <set>
17 #include <unordered_set>
18 
19 #include <benchmark/benchmark.h>
20 
21 #include "perfetto/base/logging.h"
22 #include "perfetto/ext/base/file_utils.h"
23 #include "perfetto/ext/base/utils.h"
24 #include "src/base/test/utils.h"
25 #include "src/kallsyms/kernel_symbol_map.h"
26 
27 namespace {
28 
IsBenchmarkFunctionalOnly()29 bool IsBenchmarkFunctionalOnly() {
30   return getenv("BENCHMARK_FUNCTIONAL_TEST_ONLY") != nullptr;
31 }
32 
BenchmarkArgs(benchmark::internal::Benchmark * b)33 void BenchmarkArgs(benchmark::internal::Benchmark* b) {
34   if (IsBenchmarkFunctionalOnly()) {
35     b->Ranges({{16, 16}, {16, 16}});
36   } else {
37     b->RangeMultiplier(2)->Ranges({{4, 512}, {4, 512}});
38   }
39 }
40 
41 struct ExpectedSym {
42   uint64_t addr;
43   const char* name;
44 };
45 
46 // This set of symbols has been chosen by randomly picking 40 random symbols
47 // from the original kallsyms.
48 ExpectedSym kExpectedSyms[] = {
49     {0xffffff8f79c0d978, "__map_memblock"},
50     {0xffffff8f78fddbb8, "smack_inode_getsecid"},
51     {0xffffff8f78fe43b4, "msm_smmu_set_attribute"},
52     {0xffffff8f79d23e20, "__initcall_41_dm_verity_init6"},
53     {0xffffff8f74206c5c, "sme_update_fast_transition_enabled"},
54     {0xffffff8f74878c8c, "tavil_hph_idle_detect_put"},
55     {0xffffff8f78fd7db0, "privileged_wrt_inode_uidgid"},
56     {0xffffff8f78ffe030, "__hrtimer_tasklet_trampoline"},
57     {0xffffff8f78fd86b0, "store_enable"},
58     {0xffffff8f78ffbcb8, "raw6_exit_net"},
59     {0xffffff8f78ffa6ec, "idProduct_show"},
60     {0xffffff8f78fd99c0, "perf_tp_event"},
61     {0xffffff8f78fe1468, "rpmh_tx_done"},
62     {0xffffff8f78fda274, "page_unlock_anon_vma_read"},
63     {0xffffff8f78ffedfc, "vmstat_period_ms_operations_open"},
64     {0xffffff8f78fe0148, "devm_gpio_request"},
65     {0xffffff8f77915028, "ctx_sched_out"},
66     {0xffffff8f77ccdc2c, "gcm_hash_crypt_remain_continue"},
67     {0xffffff8f790022ec, "loop_init"},
68     {0xffffff8f78ff0004, "pcim_release"},
69     {0xffffff8f78fe1d8c, "uart_close"},
70     {0xffffff8f78fda9d4, "pipe_lock"},
71     {0xffffff8f78e62c68, "local_bh_enable.117091"},
72     {0xffffff8f78fd918c, "fork_idle"},
73     {0xffffff8f78fe24c4, "drm_dp_downstream_debug"},
74     {0xffffff8f78ff41d0, "inet_addr_onlink"},
75     {0xffffff8f78fdf2d4, "idr_alloc"},
76     {0xffffff8f78ff073c, "fts_remove"},
77     {0xffffff8f78ffe294, "xfrm4_local_error"},
78     {0xffffff8f79001994, "cpu_feature_match_PMULL_init"},
79     {0xffffff8f78ff4740, "xfrm_state_find"},
80     {0xffffff8f78ff58b0, "inet_del_offload"},
81     {0xffffff8f742041ac, "csr_is_conn_state_connected_infra"},
82     {0xffffff8f78fe1fd4, "diag_add_client"},
83     {0xffffff8f78ffc000, "trace_raw_output_mm_vmscan_kswapd_sleep"},
84     {0xffffff8f78fe6388, "scsi_queue_insert"},
85     {0xffffff8f78fdd480, "selinux_sb_clone_mnt_opts"},
86     {0xffffff8f78fe0e9c, "clk_fixed_rate_recalc_rate"},
87     {0xffffff8f78fedaec, "cap_inode_killpriv"},
88     {0xffffff8f79002b64, "audio_amrwb_init"},
89 };
90 
91 }  // namespace
92 
BM_KallSymsFind(benchmark::State & state)93 static void BM_KallSymsFind(benchmark::State& state) {
94   perfetto::KernelSymbolMap::kTokenIndexSampling =
95       static_cast<size_t>(state.range(0));
96   perfetto::KernelSymbolMap::kSymIndexSampling =
97       static_cast<size_t>(state.range(1));
98   perfetto::KernelSymbolMap kallsyms;
99 
100   // Don't run the benchmark on the CI as it requires pushing all test data,
101   // which slows down significantly the CI.
102   const bool skip = IsBenchmarkFunctionalOnly();
103   if (!skip) {
104     kallsyms.Parse(perfetto::base::GetTestDataPath("test/data/kallsyms.txt"));
105   }
106 
107   for (auto _ : state) {
108     for (size_t i = 0; i < perfetto::base::ArraySize(kExpectedSyms); i++) {
109       const auto& exp = kExpectedSyms[i];
110       PERFETTO_CHECK(skip || kallsyms.Lookup(exp.addr) == exp.name);
111     }
112   }
113 
114   state.counters["mem"] = static_cast<double>(kallsyms.size_bytes());
115 }
116 
117 BENCHMARK(BM_KallSymsFind)->Apply(BenchmarkArgs);
118 
BM_KallSymsLoad(benchmark::State & state)119 static void BM_KallSymsLoad(benchmark::State& state) {
120   perfetto::KernelSymbolMap::kTokenIndexSampling =
121       static_cast<size_t>(state.range(0));
122   perfetto::KernelSymbolMap::kSymIndexSampling =
123       static_cast<size_t>(state.range(1));
124 
125   // Don't run the benchmark on the CI as it requires pushing all test data,
126   // which slows down significantly the CI.
127   const bool skip = IsBenchmarkFunctionalOnly();
128 
129   const std::string kallsyms_path =
130       perfetto::base::GetTestDataPath("test/data/kallsyms.txt");
131   if (!skip) {
132     std::string tmp;
133     // Read the whole file once, so that it's cached.
134     PERFETTO_CHECK(perfetto::base::ReadFile(kallsyms_path, &tmp));
135   }
136 
137   for (auto _ : state) {
138     perfetto::KernelSymbolMap kallsyms;
139     if (!skip) {
140       kallsyms.Parse(kallsyms_path);
141     }
142   }
143 }
144 
145 BENCHMARK(BM_KallSymsLoad)->Apply(BenchmarkArgs);
146