1 /*
2 * Copyright (C) 2020 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 <err.h>
18 #include <inttypes.h>
19 #include <malloc.h>
20 #include <stdint.h>
21
22 #include <string>
23 #include <vector>
24
25 #include <benchmark/benchmark.h>
26
27 #include <unwindstack/Elf.h>
28 #include <unwindstack/Memory.h>
29
30 #include "Utils.h"
31
32 class SymbolLookupBenchmark : public benchmark::Fixture {
33 public:
RunBenchmark(benchmark::State & state,const std::vector<uint64_t> & offsets,const std::string & elf_file,bool expect_found,uint32_t runs=1)34 void RunBenchmark(benchmark::State& state, const std::vector<uint64_t>& offsets,
35 const std::string& elf_file, bool expect_found, uint32_t runs = 1) {
36 MemoryTracker mem_tracker;
37 for (const auto& _ : state) {
38 state.PauseTiming();
39 mem_tracker.StartTrackingAllocations();
40 state.ResumeTiming();
41
42 auto elf_memory = unwindstack::Memory::CreateFileMemory(elf_file, 0);
43 unwindstack::Elf elf(elf_memory);
44 if (!elf.Init() || !elf.valid()) {
45 errx(1, "Internal Error: Cannot open elf: %s", elf_file.c_str());
46 }
47
48 unwindstack::SharedString name;
49 uint64_t offset;
50 for (size_t i = 0; i < runs; i++) {
51 for (auto pc : offsets) {
52 bool found = elf.GetFunctionName(pc, &name, &offset);
53 if (expect_found && !found) {
54 errx(1, "expected pc 0x%" PRIx64 " present, but not found.", pc);
55 } else if (!expect_found && found) {
56 errx(1, "expected pc 0x%" PRIx64 " not present, but found.", pc);
57 }
58 }
59 }
60
61 state.PauseTiming();
62 mem_tracker.StopTrackingAllocations();
63 state.ResumeTiming();
64 }
65 mem_tracker.SetBenchmarkCounters(state);
66 }
67
RunBenchmark(benchmark::State & state,uint64_t pc,const std::string & elf_file,bool expect_found,uint32_t runs=1)68 void RunBenchmark(benchmark::State& state, uint64_t pc, const std::string& elf_file,
69 bool expect_found, uint32_t runs = 1) {
70 RunBenchmark(state, std::vector<uint64_t>{pc}, elf_file, expect_found, runs);
71 }
72 };
73
BENCHMARK_F(SymbolLookupBenchmark,BM_symbol_lookup_not_present)74 BENCHMARK_F(SymbolLookupBenchmark, BM_symbol_lookup_not_present)(benchmark::State& state) {
75 RunBenchmark(state, 0, GetElfFile(), false);
76 }
77
BENCHMARK_F(SymbolLookupBenchmark,BM_symbol_lookup_find_single)78 BENCHMARK_F(SymbolLookupBenchmark, BM_symbol_lookup_find_single)(benchmark::State& state) {
79 RunBenchmark(state, 0x22b2bc, GetElfFile(), true);
80 }
81
BENCHMARK_F(SymbolLookupBenchmark,BM_symbol_lookup_find_single_many_times)82 BENCHMARK_F(SymbolLookupBenchmark, BM_symbol_lookup_find_single_many_times)
83 (benchmark::State& state) {
84 RunBenchmark(state, 0x22b2bc, GetElfFile(), true, 4096);
85 }
86
BENCHMARK_F(SymbolLookupBenchmark,BM_symbol_lookup_find_multiple)87 BENCHMARK_F(SymbolLookupBenchmark, BM_symbol_lookup_find_multiple)(benchmark::State& state) {
88 RunBenchmark(state, std::vector<uint64_t>{0x22b2bc, 0xd5d30, 0x1312e8, 0x13582e, 0x1389c8},
89 GetElfFile(), true);
90 }
91
BENCHMARK_F(SymbolLookupBenchmark,BM_symbol_lookup_not_present_from_sorted)92 BENCHMARK_F(SymbolLookupBenchmark, BM_symbol_lookup_not_present_from_sorted)
93 (benchmark::State& state) {
94 RunBenchmark(state, 0, GetSymbolSortedElfFile(), false);
95 }
96
BENCHMARK_F(SymbolLookupBenchmark,BM_symbol_lookup_find_single_from_sorted)97 BENCHMARK_F(SymbolLookupBenchmark, BM_symbol_lookup_find_single_from_sorted)
98 (benchmark::State& state) {
99 RunBenchmark(state, 0x138638, GetSymbolSortedElfFile(), true);
100 }
101
BENCHMARK_F(SymbolLookupBenchmark,BM_symbol_lookup_find_single_many_times_from_sorted)102 BENCHMARK_F(SymbolLookupBenchmark, BM_symbol_lookup_find_single_many_times_from_sorted)
103 (benchmark::State& state) {
104 RunBenchmark(state, 0x138638, GetSymbolSortedElfFile(), true, 4096);
105 }
106
BENCHMARK_F(SymbolLookupBenchmark,BM_symbol_lookup_find_multiple_from_sorted)107 BENCHMARK_F(SymbolLookupBenchmark, BM_symbol_lookup_find_multiple_from_sorted)
108 (benchmark::State& state) {
109 RunBenchmark(state, std::vector<uint64_t>{0x138638, 0x84350, 0x14df18, 0x1f3a38, 0x1f3ca8},
110 GetSymbolSortedElfFile(), true);
111 }
112
BENCHMARK_F(SymbolLookupBenchmark,BM_symbol_lookup_not_present_from_large_compressed_frame)113 BENCHMARK_F(SymbolLookupBenchmark, BM_symbol_lookup_not_present_from_large_compressed_frame)
114 (benchmark::State& state) {
115 RunBenchmark(state, 0, GetLargeCompressedFrameElfFile(), false);
116 }
117
BENCHMARK_F(SymbolLookupBenchmark,BM_symbol_lookup_find_single_from_large_compressed_frame)118 BENCHMARK_F(SymbolLookupBenchmark, BM_symbol_lookup_find_single_from_large_compressed_frame)
119 (benchmark::State& state) {
120 RunBenchmark(state, 0x202aec, GetLargeCompressedFrameElfFile(), true);
121 }
122
BENCHMARK_F(SymbolLookupBenchmark,BM_symbol_lookup_find_single_many_times_from_large_compressed_frame)123 BENCHMARK_F(SymbolLookupBenchmark,
124 BM_symbol_lookup_find_single_many_times_from_large_compressed_frame)
125 (benchmark::State& state) {
126 RunBenchmark(state, 0x202aec, GetLargeCompressedFrameElfFile(), true, 4096);
127 }
128
BENCHMARK_F(SymbolLookupBenchmark,BM_symbol_lookup_find_multiple_from_large_compressed_frame)129 BENCHMARK_F(SymbolLookupBenchmark, BM_symbol_lookup_find_multiple_from_large_compressed_frame)
130 (benchmark::State& state) {
131 RunBenchmark(state, std::vector<uint64_t>{0x202aec, 0x23e74c, 0xd000c, 0x201b10, 0x183060},
132 GetLargeCompressedFrameElfFile(), true);
133 }
134