1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker *
4*eb293b8fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker *
8*eb293b8fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker *
10*eb293b8fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker */
16*eb293b8fSAndroid Build Coastguard Worker
17*eb293b8fSAndroid Build Coastguard Worker #include <err.h>
18*eb293b8fSAndroid Build Coastguard Worker #include <malloc.h>
19*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
20*eb293b8fSAndroid Build Coastguard Worker
21*eb293b8fSAndroid Build Coastguard Worker #include <string>
22*eb293b8fSAndroid Build Coastguard Worker
23*eb293b8fSAndroid Build Coastguard Worker #include <benchmark/benchmark.h>
24*eb293b8fSAndroid Build Coastguard Worker
25*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Elf.h>
26*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Maps.h>
27*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
28*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Regs.h>
29*eb293b8fSAndroid Build Coastguard Worker
30*eb293b8fSAndroid Build Coastguard Worker #include "Utils.h"
31*eb293b8fSAndroid Build Coastguard Worker
32*eb293b8fSAndroid Build Coastguard Worker class ElfCreateBenchmark : public benchmark::Fixture {
33*eb293b8fSAndroid Build Coastguard Worker public:
RunBenchmark(benchmark::State & state,const std::string & elf_file)34*eb293b8fSAndroid Build Coastguard Worker void RunBenchmark(benchmark::State& state, const std::string& elf_file) {
35*eb293b8fSAndroid Build Coastguard Worker MemoryTracker mem_tracker;
36*eb293b8fSAndroid Build Coastguard Worker for (const auto& _ : state) {
37*eb293b8fSAndroid Build Coastguard Worker state.PauseTiming();
38*eb293b8fSAndroid Build Coastguard Worker mem_tracker.StartTrackingAllocations();
39*eb293b8fSAndroid Build Coastguard Worker
40*eb293b8fSAndroid Build Coastguard Worker auto file_memory = unwindstack::Memory::CreateFileMemory(elf_file, 0);
41*eb293b8fSAndroid Build Coastguard Worker state.ResumeTiming();
42*eb293b8fSAndroid Build Coastguard Worker
43*eb293b8fSAndroid Build Coastguard Worker unwindstack::Elf elf(file_memory);
44*eb293b8fSAndroid Build Coastguard Worker if (!elf.Init() || !elf.valid()) {
45*eb293b8fSAndroid Build Coastguard Worker errx(1, "Internal Error: Cannot open elf: %s", elf_file.c_str());
46*eb293b8fSAndroid Build Coastguard Worker }
47*eb293b8fSAndroid Build Coastguard Worker
48*eb293b8fSAndroid Build Coastguard Worker state.PauseTiming();
49*eb293b8fSAndroid Build Coastguard Worker mem_tracker.StopTrackingAllocations();
50*eb293b8fSAndroid Build Coastguard Worker state.ResumeTiming();
51*eb293b8fSAndroid Build Coastguard Worker }
52*eb293b8fSAndroid Build Coastguard Worker mem_tracker.SetBenchmarkCounters(state);
53*eb293b8fSAndroid Build Coastguard Worker }
54*eb293b8fSAndroid Build Coastguard Worker };
55*eb293b8fSAndroid Build Coastguard Worker
BENCHMARK_F(ElfCreateBenchmark,BM_elf_create)56*eb293b8fSAndroid Build Coastguard Worker BENCHMARK_F(ElfCreateBenchmark, BM_elf_create)(benchmark::State& state) {
57*eb293b8fSAndroid Build Coastguard Worker RunBenchmark(state, GetElfFile());
58*eb293b8fSAndroid Build Coastguard Worker }
59*eb293b8fSAndroid Build Coastguard Worker
BENCHMARK_F(ElfCreateBenchmark,BM_elf_create_large_compressed)60*eb293b8fSAndroid Build Coastguard Worker BENCHMARK_F(ElfCreateBenchmark, BM_elf_create_large_compressed)(benchmark::State& state) {
61*eb293b8fSAndroid Build Coastguard Worker RunBenchmark(state, GetLargeCompressedFrameElfFile());
62*eb293b8fSAndroid Build Coastguard Worker }
63*eb293b8fSAndroid Build Coastguard Worker
BENCHMARK_F(ElfCreateBenchmark,BM_elf_create_large_eh_frame)64*eb293b8fSAndroid Build Coastguard Worker BENCHMARK_F(ElfCreateBenchmark, BM_elf_create_large_eh_frame)(benchmark::State& state) {
65*eb293b8fSAndroid Build Coastguard Worker RunBenchmark(state, GetLargeEhFrameElfFile());
66*eb293b8fSAndroid Build Coastguard Worker }
67*eb293b8fSAndroid Build Coastguard Worker
InitializeBuildId(benchmark::State & state,unwindstack::Maps & maps,unwindstack::MapInfo ** build_id_map_info)68*eb293b8fSAndroid Build Coastguard Worker static void InitializeBuildId(benchmark::State& state, unwindstack::Maps& maps,
69*eb293b8fSAndroid Build Coastguard Worker unwindstack::MapInfo** build_id_map_info) {
70*eb293b8fSAndroid Build Coastguard Worker if (!maps.Parse()) {
71*eb293b8fSAndroid Build Coastguard Worker state.SkipWithError("Failed to parse local maps.");
72*eb293b8fSAndroid Build Coastguard Worker return;
73*eb293b8fSAndroid Build Coastguard Worker }
74*eb293b8fSAndroid Build Coastguard Worker
75*eb293b8fSAndroid Build Coastguard Worker // Find the libc.so share library and use that for benchmark purposes.
76*eb293b8fSAndroid Build Coastguard Worker *build_id_map_info = nullptr;
77*eb293b8fSAndroid Build Coastguard Worker for (auto& map_info : maps) {
78*eb293b8fSAndroid Build Coastguard Worker if (map_info->offset() == 0 && map_info->GetBuildID() != "") {
79*eb293b8fSAndroid Build Coastguard Worker *build_id_map_info = map_info.get();
80*eb293b8fSAndroid Build Coastguard Worker break;
81*eb293b8fSAndroid Build Coastguard Worker }
82*eb293b8fSAndroid Build Coastguard Worker }
83*eb293b8fSAndroid Build Coastguard Worker
84*eb293b8fSAndroid Build Coastguard Worker if (*build_id_map_info == nullptr) {
85*eb293b8fSAndroid Build Coastguard Worker state.SkipWithError("Failed to find a map with a BuildID.");
86*eb293b8fSAndroid Build Coastguard Worker }
87*eb293b8fSAndroid Build Coastguard Worker }
88*eb293b8fSAndroid Build Coastguard Worker
BM_elf_get_build_id_from_object(benchmark::State & state)89*eb293b8fSAndroid Build Coastguard Worker static void BM_elf_get_build_id_from_object(benchmark::State& state) {
90*eb293b8fSAndroid Build Coastguard Worker unwindstack::LocalMaps maps;
91*eb293b8fSAndroid Build Coastguard Worker unwindstack::MapInfo* build_id_map_info;
92*eb293b8fSAndroid Build Coastguard Worker InitializeBuildId(state, maps, &build_id_map_info);
93*eb293b8fSAndroid Build Coastguard Worker
94*eb293b8fSAndroid Build Coastguard Worker unwindstack::Elf* elf = build_id_map_info->GetElf(std::shared_ptr<unwindstack::Memory>(),
95*eb293b8fSAndroid Build Coastguard Worker unwindstack::Regs::CurrentArch());
96*eb293b8fSAndroid Build Coastguard Worker if (!elf->valid()) {
97*eb293b8fSAndroid Build Coastguard Worker state.SkipWithError("Cannot get valid elf from map.");
98*eb293b8fSAndroid Build Coastguard Worker }
99*eb293b8fSAndroid Build Coastguard Worker
100*eb293b8fSAndroid Build Coastguard Worker for (const auto& _ : state) {
101*eb293b8fSAndroid Build Coastguard Worker state.PauseTiming();
102*eb293b8fSAndroid Build Coastguard Worker unwindstack::SharedString* id = build_id_map_info->build_id();
103*eb293b8fSAndroid Build Coastguard Worker if (id != nullptr) {
104*eb293b8fSAndroid Build Coastguard Worker delete id;
105*eb293b8fSAndroid Build Coastguard Worker build_id_map_info->set_build_id(nullptr);
106*eb293b8fSAndroid Build Coastguard Worker }
107*eb293b8fSAndroid Build Coastguard Worker state.ResumeTiming();
108*eb293b8fSAndroid Build Coastguard Worker benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
109*eb293b8fSAndroid Build Coastguard Worker }
110*eb293b8fSAndroid Build Coastguard Worker }
111*eb293b8fSAndroid Build Coastguard Worker BENCHMARK(BM_elf_get_build_id_from_object);
112*eb293b8fSAndroid Build Coastguard Worker
BM_elf_get_build_id_from_file(benchmark::State & state)113*eb293b8fSAndroid Build Coastguard Worker static void BM_elf_get_build_id_from_file(benchmark::State& state) {
114*eb293b8fSAndroid Build Coastguard Worker unwindstack::LocalMaps maps;
115*eb293b8fSAndroid Build Coastguard Worker unwindstack::MapInfo* build_id_map_info;
116*eb293b8fSAndroid Build Coastguard Worker InitializeBuildId(state, maps, &build_id_map_info);
117*eb293b8fSAndroid Build Coastguard Worker
118*eb293b8fSAndroid Build Coastguard Worker for (const auto& _ : state) {
119*eb293b8fSAndroid Build Coastguard Worker state.PauseTiming();
120*eb293b8fSAndroid Build Coastguard Worker unwindstack::SharedString* id = build_id_map_info->build_id();
121*eb293b8fSAndroid Build Coastguard Worker if (id != nullptr) {
122*eb293b8fSAndroid Build Coastguard Worker delete id;
123*eb293b8fSAndroid Build Coastguard Worker build_id_map_info->set_build_id(nullptr);
124*eb293b8fSAndroid Build Coastguard Worker }
125*eb293b8fSAndroid Build Coastguard Worker state.ResumeTiming();
126*eb293b8fSAndroid Build Coastguard Worker benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
127*eb293b8fSAndroid Build Coastguard Worker }
128*eb293b8fSAndroid Build Coastguard Worker }
129*eb293b8fSAndroid Build Coastguard Worker BENCHMARK(BM_elf_get_build_id_from_file);
130