blob: a850ff047fdcff0cdb6afa20c2266812b75eea8a [file] [log] [blame]
Christopher Ferrisa9e19092020-04-14 11:59:15 -07001/*
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 <android-base/file.h>
26#include <android-base/strings.h>
27#include <benchmark/benchmark.h>
28
29#include <unwindstack/Elf.h>
30#include <unwindstack/Memory.h>
31
32#if defined(__BIONIC__)
33
34#include <meminfo/procmeminfo.h>
35#include <procinfo/process_map.h>
36
37static void Gather(uint64_t* rss_bytes) {
38 android::meminfo::ProcMemInfo proc_mem(getpid());
39 const std::vector<android::meminfo::Vma>& maps = proc_mem.MapsWithoutUsageStats();
40 for (auto& vma : maps) {
41 if (vma.name == "[anon:libc_malloc]" || android::base::StartsWith(vma.name, "[anon:scudo:") ||
42 android::base::StartsWith(vma.name, "[anon:GWP-ASan")) {
43 android::meminfo::Vma update_vma(vma);
44 if (!proc_mem.FillInVmaStats(update_vma)) {
45 err(1, "FillInVmaStats failed\n");
46 }
47 *rss_bytes += update_vma.usage.rss;
48 }
49 }
50}
51#endif
52
53static void BenchmarkSymbolLookup(benchmark::State& state, std::vector<uint64_t> offsets,
54 std::string elf_file, bool expect_found) {
55#if defined(__BIONIC__)
56 uint64_t rss_bytes = 0;
57#endif
58 uint64_t alloc_bytes = 0;
59 for (auto _ : state) {
60 state.PauseTiming();
61 unwindstack::Elf elf(unwindstack::Memory::CreateFileMemory(elf_file, 0).release());
62 if (!elf.Init() || !elf.valid()) {
63 errx(1, "Internal Error: Cannot open elf.");
64 }
65
66#if defined(__BIONIC__)
67 mallopt(M_PURGE, 0);
68 uint64_t rss_bytes_before = 0;
69 Gather(&rss_bytes_before);
70#endif
71 uint64_t alloc_bytes_before = mallinfo().uordblks;
72 state.ResumeTiming();
73
74 for (auto pc : offsets) {
75 std::string name;
76 uint64_t offset;
77 bool found = elf.GetFunctionName(pc, &name, &offset);
78 if (expect_found && !found) {
79 errx(1, "expected pc 0x%" PRIx64 " present, but not found.", pc);
80 } else if (!expect_found && found) {
81 errx(1, "expected pc 0x%" PRIx64 " not present, but found.", pc);
82 }
83 }
84
85 state.PauseTiming();
86#if defined(__BIONIC__)
87 mallopt(M_PURGE, 0);
88#endif
89 alloc_bytes += mallinfo().uordblks - alloc_bytes_before;
90#if defined(__BIONIC__)
91 Gather(&rss_bytes);
92 rss_bytes -= rss_bytes_before;
93#endif
94 state.ResumeTiming();
95 }
96
97#if defined(__BIONIC__)
98 state.counters["RSS_BYTES"] = rss_bytes / static_cast<double>(state.iterations());
99#endif
100 state.counters["ALLOCATED_BYTES"] = alloc_bytes / static_cast<double>(state.iterations());
101}
102
103static void BenchmarkSymbolLookup(benchmark::State& state, uint64_t pc, std::string elf_file,
104 bool expect_found) {
105 BenchmarkSymbolLookup(state, std::vector<uint64_t>{pc}, elf_file, expect_found);
106}
107
108std::string GetElfFile() {
109 return android::base::GetExecutableDirectory() + "/benchmarks/files/libart_arm.so";
110}
111
112std::string GetSortedElfFile() {
113 return android::base::GetExecutableDirectory() + "/benchmarks/files/boot_arm.oat";
114}
115
116void BM_symbol_not_present(benchmark::State& state) {
117 BenchmarkSymbolLookup(state, 0, GetElfFile(), false);
118}
119BENCHMARK(BM_symbol_not_present);
120
121void BM_symbol_find_single(benchmark::State& state) {
122 BenchmarkSymbolLookup(state, 0x22b2bc, GetElfFile(), true);
123}
124BENCHMARK(BM_symbol_find_single);
125
126void BM_symbol_find_single_many_times(benchmark::State& state) {
127 BenchmarkSymbolLookup(state, std::vector<uint64_t>(15, 0x22b2bc), GetElfFile(), true);
128}
129BENCHMARK(BM_symbol_find_single_many_times);
130
131void BM_symbol_find_multiple(benchmark::State& state) {
132 BenchmarkSymbolLookup(state,
133 std::vector<uint64_t>{0x22b2bc, 0xd5d30, 0x1312e8, 0x13582e, 0x1389c8},
134 GetElfFile(), true);
135}
136BENCHMARK(BM_symbol_find_multiple);
137
138void BM_symbol_not_present_from_sorted(benchmark::State& state) {
139 BenchmarkSymbolLookup(state, 0, GetSortedElfFile(), false);
140}
141BENCHMARK(BM_symbol_not_present_from_sorted);
142
143void BM_symbol_find_single_from_sorted(benchmark::State& state) {
144 BenchmarkSymbolLookup(state, 0x138638, GetSortedElfFile(), true);
145}
146BENCHMARK(BM_symbol_find_single_from_sorted);
147
148void BM_symbol_find_single_many_times_from_sorted(benchmark::State& state) {
149 BenchmarkSymbolLookup(state, std::vector<uint64_t>(15, 0x138638), GetSortedElfFile(), true);
150}
151BENCHMARK(BM_symbol_find_single_many_times_from_sorted);
152
153void BM_symbol_find_multiple_from_sorted(benchmark::State& state) {
154 BenchmarkSymbolLookup(state,
155 std::vector<uint64_t>{0x138638, 0x84350, 0x14df18, 0x1f3a38, 0x1f3ca8},
156 GetSortedElfFile(), true);
157}
158BENCHMARK(BM_symbol_find_multiple_from_sorted);