xref: /aosp_15_r20/system/unwinding/libunwindstack/benchmarks/ElfBenchmark.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
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