• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
BenchmarkElfCreate(benchmark::State & state,const std::string & elf_file)32 static void BenchmarkElfCreate(benchmark::State& state, const std::string& elf_file) {
33 #if defined(__BIONIC__)
34   uint64_t rss_bytes = 0;
35 #endif
36   uint64_t alloc_bytes = 0;
37   for (auto _ : state) {
38     state.PauseTiming();
39 #if defined(__BIONIC__)
40     mallopt(M_PURGE, 0);
41     uint64_t rss_bytes_before = 0;
42     GatherRss(&rss_bytes_before);
43 #endif
44     uint64_t alloc_bytes_before = mallinfo().uordblks;
45     auto file_memory = unwindstack::Memory::CreateFileMemory(elf_file, 0);
46     state.ResumeTiming();
47 
48     unwindstack::Elf elf(file_memory.release());
49     if (!elf.Init() || !elf.valid()) {
50       errx(1, "Internal Error: Cannot open elf: %s", elf_file.c_str());
51     }
52 
53     state.PauseTiming();
54 #if defined(__BIONIC__)
55     mallopt(M_PURGE, 0);
56 #endif
57     alloc_bytes += mallinfo().uordblks - alloc_bytes_before;
58 #if defined(__BIONIC__)
59     GatherRss(&rss_bytes);
60     rss_bytes -= rss_bytes_before;
61 #endif
62     state.ResumeTiming();
63   }
64 
65 #if defined(__BIONIC__)
66   state.counters["RSS_BYTES"] = rss_bytes / static_cast<double>(state.iterations());
67 #endif
68   state.counters["ALLOCATED_BYTES"] = alloc_bytes / static_cast<double>(state.iterations());
69 }
70 
BM_elf_create(benchmark::State & state)71 void BM_elf_create(benchmark::State& state) {
72   BenchmarkElfCreate(state, GetElfFile());
73 }
74 BENCHMARK(BM_elf_create);
75 
BM_elf_create_large_compressed(benchmark::State & state)76 void BM_elf_create_large_compressed(benchmark::State& state) {
77   BenchmarkElfCreate(state, GetLargeCompressedFrameElfFile());
78 }
79 BENCHMARK(BM_elf_create_large_compressed);
80 
BM_elf_create_large_eh_frame(benchmark::State & state)81 void BM_elf_create_large_eh_frame(benchmark::State& state) {
82   BenchmarkElfCreate(state, GetLargeEhFrameElfFile());
83 }
84 BENCHMARK(BM_elf_create_large_eh_frame);
85 
InitializeBuildId(benchmark::State & state,unwindstack::Maps & maps,unwindstack::MapInfo ** build_id_map_info)86 static void InitializeBuildId(benchmark::State& state, unwindstack::Maps& maps,
87                               unwindstack::MapInfo** build_id_map_info) {
88   if (!maps.Parse()) {
89     state.SkipWithError("Failed to parse local maps.");
90     return;
91   }
92 
93   // Find the libc.so share library and use that for benchmark purposes.
94   *build_id_map_info = nullptr;
95   for (auto& map_info : maps) {
96     if (map_info->offset() == 0 && map_info->GetBuildID() != "") {
97       *build_id_map_info = map_info.get();
98       break;
99     }
100   }
101 
102   if (*build_id_map_info == nullptr) {
103     state.SkipWithError("Failed to find a map with a BuildID.");
104   }
105 }
106 
BM_elf_get_build_id_from_object(benchmark::State & state)107 static void BM_elf_get_build_id_from_object(benchmark::State& state) {
108   unwindstack::LocalMaps maps;
109   unwindstack::MapInfo* build_id_map_info;
110   InitializeBuildId(state, maps, &build_id_map_info);
111 
112   unwindstack::Elf* elf = build_id_map_info->GetElf(std::shared_ptr<unwindstack::Memory>(),
113                                                     unwindstack::Regs::CurrentArch());
114   if (!elf->valid()) {
115     state.SkipWithError("Cannot get valid elf from map.");
116   }
117 
118   for (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_object);
130 
BM_elf_get_build_id_from_file(benchmark::State & state)131 static void BM_elf_get_build_id_from_file(benchmark::State& state) {
132   unwindstack::LocalMaps maps;
133   unwindstack::MapInfo* build_id_map_info;
134   InitializeBuildId(state, maps, &build_id_map_info);
135 
136   for (auto _ : state) {
137     state.PauseTiming();
138     unwindstack::SharedString* id = build_id_map_info->build_id();
139     if (id != nullptr) {
140       delete id;
141       build_id_map_info->set_build_id(nullptr);
142     }
143     state.ResumeTiming();
144     benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
145   }
146 }
147 BENCHMARK(BM_elf_get_build_id_from_file);
148