blob: a46bd7a242fca5e9b8f0aace21c09f5ca3307242 [file] [log] [blame]
David Srbeckya17c2b62020-04-14 16:59:27 +01001/*
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>
Christopher Ferris175747f2020-05-04 13:46:09 -070026#include <unwindstack/Maps.h>
David Srbeckya17c2b62020-04-14 16:59:27 +010027#include <unwindstack/Memory.h>
Christopher Ferris175747f2020-05-04 13:46:09 -070028#include <unwindstack/Regs.h>
David Srbeckya17c2b62020-04-14 16:59:27 +010029
30#include "Utils.h"
31
32static 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.");
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
71void BM_elf_create(benchmark::State& state) {
72 BenchmarkElfCreate(state, GetElfFile());
73}
74BENCHMARK(BM_elf_create);
75
76void BM_elf_create_compressed(benchmark::State& state) {
77 BenchmarkElfCreate(state, GetCompressedElfFile());
78}
79BENCHMARK(BM_elf_create_compressed);
Christopher Ferris175747f2020-05-04 13:46:09 -070080
81static void InitializeBuildId(benchmark::State& state, unwindstack::Maps& maps,
82 unwindstack::MapInfo** build_id_map_info) {
83 if (!maps.Parse()) {
84 state.SkipWithError("Failed to parse local maps.");
85 return;
86 }
87
88 // Find the libc.so share library and use that for benchmark purposes.
89 *build_id_map_info = nullptr;
90 for (auto& map_info : maps) {
91 if (map_info->offset == 0 && map_info->GetBuildID() != "") {
92 *build_id_map_info = map_info.get();
93 break;
94 }
95 }
96
97 if (*build_id_map_info == nullptr) {
98 state.SkipWithError("Failed to find a map with a BuildID.");
99 }
100}
101
102static void BM_elf_get_build_id_from_object(benchmark::State& state) {
103 unwindstack::LocalMaps maps;
104 unwindstack::MapInfo* build_id_map_info;
105 InitializeBuildId(state, maps, &build_id_map_info);
106
107 unwindstack::Elf* elf = build_id_map_info->GetElf(std::shared_ptr<unwindstack::Memory>(),
108 unwindstack::Regs::CurrentArch());
109 if (!elf->valid()) {
110 state.SkipWithError("Cannot get valid elf from map.");
111 }
112
113 for (auto _ : state) {
114 state.PauseTiming();
115 uintptr_t id = build_id_map_info->build_id;
116 if (id != 0) {
117 delete reinterpret_cast<std::string*>(id);
118 build_id_map_info->build_id = 0;
119 }
120 state.ResumeTiming();
121 benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
122 }
123}
124BENCHMARK(BM_elf_get_build_id_from_object);
125
126static void BM_elf_get_build_id_from_file(benchmark::State& state) {
127 unwindstack::LocalMaps maps;
128 unwindstack::MapInfo* build_id_map_info;
129 InitializeBuildId(state, maps, &build_id_map_info);
130
131 for (auto _ : state) {
132 state.PauseTiming();
133 uintptr_t id = build_id_map_info->build_id;
134 if (id != 0) {
135 delete reinterpret_cast<std::string*>(id);
136 build_id_map_info->build_id = 0;
137 }
138 state.ResumeTiming();
139 benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
140 }
141}
142BENCHMARK(BM_elf_get_build_id_from_file);