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 <malloc.h>
19 #include <stdint.h>
20
21 #include <string>
22
23 #include <benchmark/benchmark.h>
24
25 #include <unwindstack/Elf.h>
26 #include <unwindstack/Maps.h>
27 #include <unwindstack/Memory.h>
28 #include <unwindstack/Regs.h>
29
30 #include "Utils.h"
31
32 class ElfCreateBenchmark : public benchmark::Fixture {
33 public:
RunBenchmark(benchmark::State & state,const std::string & elf_file)34 void RunBenchmark(benchmark::State& state, const std::string& elf_file) {
35 MemoryTracker mem_tracker;
36 for (const auto& _ : state) {
37 state.PauseTiming();
38 mem_tracker.StartTrackingAllocations();
39
40 auto file_memory = unwindstack::Memory::CreateFileMemory(elf_file, 0);
41 state.ResumeTiming();
42
43 unwindstack::Elf elf(file_memory);
44 if (!elf.Init() || !elf.valid()) {
45 errx(1, "Internal Error: Cannot open elf: %s", elf_file.c_str());
46 }
47
48 state.PauseTiming();
49 mem_tracker.StopTrackingAllocations();
50 state.ResumeTiming();
51 }
52 mem_tracker.SetBenchmarkCounters(state);
53 }
54 };
55
BENCHMARK_F(ElfCreateBenchmark,BM_elf_create)56 BENCHMARK_F(ElfCreateBenchmark, BM_elf_create)(benchmark::State& state) {
57 RunBenchmark(state, GetElfFile());
58 }
59
BENCHMARK_F(ElfCreateBenchmark,BM_elf_create_large_compressed)60 BENCHMARK_F(ElfCreateBenchmark, BM_elf_create_large_compressed)(benchmark::State& state) {
61 RunBenchmark(state, GetLargeCompressedFrameElfFile());
62 }
63
BENCHMARK_F(ElfCreateBenchmark,BM_elf_create_large_eh_frame)64 BENCHMARK_F(ElfCreateBenchmark, BM_elf_create_large_eh_frame)(benchmark::State& state) {
65 RunBenchmark(state, GetLargeEhFrameElfFile());
66 }
67
InitializeBuildId(benchmark::State & state,unwindstack::Maps & maps,unwindstack::MapInfo ** build_id_map_info)68 static void InitializeBuildId(benchmark::State& state, unwindstack::Maps& maps,
69 unwindstack::MapInfo** build_id_map_info) {
70 if (!maps.Parse()) {
71 state.SkipWithError("Failed to parse local maps.");
72 return;
73 }
74
75 // Find the libc.so share library and use that for benchmark purposes.
76 *build_id_map_info = nullptr;
77 for (auto& map_info : maps) {
78 if (map_info->offset() == 0 && map_info->GetBuildID() != "") {
79 *build_id_map_info = map_info.get();
80 break;
81 }
82 }
83
84 if (*build_id_map_info == nullptr) {
85 state.SkipWithError("Failed to find a map with a BuildID.");
86 }
87 }
88
BM_elf_get_build_id_from_object(benchmark::State & state)89 static void BM_elf_get_build_id_from_object(benchmark::State& state) {
90 unwindstack::LocalMaps maps;
91 unwindstack::MapInfo* build_id_map_info;
92 InitializeBuildId(state, maps, &build_id_map_info);
93
94 unwindstack::Elf* elf = build_id_map_info->GetElf(std::shared_ptr<unwindstack::Memory>(),
95 unwindstack::Regs::CurrentArch());
96 if (!elf->valid()) {
97 state.SkipWithError("Cannot get valid elf from map.");
98 }
99
100 for (const auto& _ : state) {
101 state.PauseTiming();
102 unwindstack::SharedString* id = build_id_map_info->build_id();
103 if (id != nullptr) {
104 delete id;
105 build_id_map_info->set_build_id(nullptr);
106 }
107 state.ResumeTiming();
108 benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
109 }
110 }
111 BENCHMARK(BM_elf_get_build_id_from_object);
112
BM_elf_get_build_id_from_file(benchmark::State & state)113 static void BM_elf_get_build_id_from_file(benchmark::State& state) {
114 unwindstack::LocalMaps maps;
115 unwindstack::MapInfo* build_id_map_info;
116 InitializeBuildId(state, maps, &build_id_map_info);
117
118 for (const auto& _ : state) {
119 state.PauseTiming();
120 unwindstack::SharedString* id = build_id_map_info->build_id();
121 if (id != nullptr) {
122 delete id;
123 build_id_map_info->set_build_id(nullptr);
124 }
125 state.ResumeTiming();
126 benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
127 }
128 }
129 BENCHMARK(BM_elf_get_build_id_from_file);
130