From 175747fefa394aa103a402eb4e6568b9feb8f69c Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Mon, 4 May 2020 13:46:09 -0700 Subject: [PATCH] Add new LocalUpdatableMaps benchmarks. In addition, move a couple of elf benchmarks out of unwind_benchmarks.cpp to the ElfBenchmarks.cpp file. Test: Ran benchmarks. Change-Id: I169f89f7b2dd6735568143f2176301e181fb8262 --- libunwindstack/Android.bp | 1 + libunwindstack/benchmarks/ElfBenchmark.cpp | 65 +++++++++++++ libunwindstack/benchmarks/MapsBenchmark.cpp | 93 +++++++++++++++++++ .../benchmarks/unwind_benchmarks.cpp | 60 ------------ 4 files changed, 159 insertions(+), 60 deletions(-) create mode 100644 libunwindstack/benchmarks/MapsBenchmark.cpp diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp index f3d3f2745..601904a40 100644 --- a/libunwindstack/Android.bp +++ b/libunwindstack/Android.bp @@ -411,6 +411,7 @@ cc_benchmark { srcs: [ "benchmarks/unwind_benchmarks.cpp", "benchmarks/ElfBenchmark.cpp", + "benchmarks/MapsBenchmark.cpp", "benchmarks/SymbolBenchmark.cpp", "benchmarks/Utils.cpp", ], diff --git a/libunwindstack/benchmarks/ElfBenchmark.cpp b/libunwindstack/benchmarks/ElfBenchmark.cpp index c108a2aa7..a46bd7a24 100644 --- a/libunwindstack/benchmarks/ElfBenchmark.cpp +++ b/libunwindstack/benchmarks/ElfBenchmark.cpp @@ -23,7 +23,9 @@ #include #include +#include #include +#include #include "Utils.h" @@ -75,3 +77,66 @@ void BM_elf_create_compressed(benchmark::State& state) { BenchmarkElfCreate(state, GetCompressedElfFile()); } BENCHMARK(BM_elf_create_compressed); + +static void InitializeBuildId(benchmark::State& state, unwindstack::Maps& maps, + unwindstack::MapInfo** build_id_map_info) { + if (!maps.Parse()) { + state.SkipWithError("Failed to parse local maps."); + return; + } + + // Find the libc.so share library and use that for benchmark purposes. + *build_id_map_info = nullptr; + for (auto& map_info : maps) { + if (map_info->offset == 0 && map_info->GetBuildID() != "") { + *build_id_map_info = map_info.get(); + break; + } + } + + if (*build_id_map_info == nullptr) { + state.SkipWithError("Failed to find a map with a BuildID."); + } +} + +static void BM_elf_get_build_id_from_object(benchmark::State& state) { + unwindstack::LocalMaps maps; + unwindstack::MapInfo* build_id_map_info; + InitializeBuildId(state, maps, &build_id_map_info); + + unwindstack::Elf* elf = build_id_map_info->GetElf(std::shared_ptr(), + unwindstack::Regs::CurrentArch()); + if (!elf->valid()) { + state.SkipWithError("Cannot get valid elf from map."); + } + + for (auto _ : state) { + state.PauseTiming(); + uintptr_t id = build_id_map_info->build_id; + if (id != 0) { + delete reinterpret_cast(id); + build_id_map_info->build_id = 0; + } + state.ResumeTiming(); + benchmark::DoNotOptimize(build_id_map_info->GetBuildID()); + } +} +BENCHMARK(BM_elf_get_build_id_from_object); + +static void BM_elf_get_build_id_from_file(benchmark::State& state) { + unwindstack::LocalMaps maps; + unwindstack::MapInfo* build_id_map_info; + InitializeBuildId(state, maps, &build_id_map_info); + + for (auto _ : state) { + state.PauseTiming(); + uintptr_t id = build_id_map_info->build_id; + if (id != 0) { + delete reinterpret_cast(id); + build_id_map_info->build_id = 0; + } + state.ResumeTiming(); + benchmark::DoNotOptimize(build_id_map_info->GetBuildID()); + } +} +BENCHMARK(BM_elf_get_build_id_from_file); diff --git a/libunwindstack/benchmarks/MapsBenchmark.cpp b/libunwindstack/benchmarks/MapsBenchmark.cpp new file mode 100644 index 000000000..be106a3a3 --- /dev/null +++ b/libunwindstack/benchmarks/MapsBenchmark.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include +#include + +#include + +#include + +class BenchmarkLocalUpdatableMaps : public unwindstack::LocalUpdatableMaps { + public: + BenchmarkLocalUpdatableMaps() : unwindstack::LocalUpdatableMaps() {} + virtual ~BenchmarkLocalUpdatableMaps() = default; + + const std::string GetMapsFile() const override { return maps_file_; } + + void BenchmarkSetMapsFile(const std::string& maps_file) { maps_file_ = maps_file; } + + private: + std::string maps_file_; +}; + +constexpr size_t kNumMaps = 10000; + +static void CreateInitialMap(const char* filename) { + std::string maps; + for (size_t i = 0; i < kNumMaps; i += 2) { + maps += android::base::StringPrintf("%zu-%zu r-xp 0000 00:00 0 name%zu\n", i * 1000, + (i + 1) * 1000, i); + } + if (!android::base::WriteStringToFile(maps, filename)) { + errx(1, "WriteStringToFile failed"); + } +} + +static void CreateReparseMap(const char* filename) { + std::string maps; + for (size_t i = 0; i < kNumMaps; i++) { + maps += android::base::StringPrintf("%zu-%zu r-xp 0000 00:00 0 name%zu\n", i * 2000, + (i + 1) * 2000, 2 * i); + } + if (!android::base::WriteStringToFile(maps, filename)) { + errx(1, "WriteStringToFile failed"); + } +} + +void BM_local_updatable_maps_reparse(benchmark::State& state) { + TemporaryFile initial_map; + CreateInitialMap(initial_map.path); + + TemporaryFile reparse_map; + CreateReparseMap(reparse_map.path); + + for (auto _ : state) { + BenchmarkLocalUpdatableMaps maps; + maps.BenchmarkSetMapsFile(initial_map.path); + if (!maps.Reparse()) { + errx(1, "Internal Error: reparse of initial maps filed."); + } + if (maps.Total() != (kNumMaps / 2)) { + errx(1, "Internal Error: Incorrect total number of maps %zu, expected %zu.", maps.Total(), + kNumMaps / 2); + } + maps.BenchmarkSetMapsFile(reparse_map.path); + if (!maps.Reparse()) { + errx(1, "Internal Error: reparse of second set of maps filed."); + } + if (maps.Total() != kNumMaps) { + errx(1, "Internal Error: Incorrect total number of maps %zu, expected %zu.", maps.Total(), + kNumMaps); + } + } +} +BENCHMARK(BM_local_updatable_maps_reparse); diff --git a/libunwindstack/benchmarks/unwind_benchmarks.cpp b/libunwindstack/benchmarks/unwind_benchmarks.cpp index de9137aa4..0bee6ef78 100644 --- a/libunwindstack/benchmarks/unwind_benchmarks.cpp +++ b/libunwindstack/benchmarks/unwind_benchmarks.cpp @@ -22,7 +22,6 @@ #include -#include #include #include #include @@ -83,63 +82,4 @@ static void BM_cached_unwind(benchmark::State& state) { } BENCHMARK(BM_cached_unwind); -static void Initialize(benchmark::State& state, unwindstack::Maps& maps, - unwindstack::MapInfo** build_id_map_info) { - if (!maps.Parse()) { - state.SkipWithError("Failed to parse local maps."); - return; - } - - // Find the libc.so share library and use that for benchmark purposes. - *build_id_map_info = nullptr; - for (auto& map_info : maps) { - if (map_info->offset == 0 && map_info->GetBuildID() != "") { - *build_id_map_info = map_info.get(); - break; - } - } - - if (*build_id_map_info == nullptr) { - state.SkipWithError("Failed to find a map with a BuildID."); - } -} - -static void BM_get_build_id_from_elf(benchmark::State& state) { - unwindstack::LocalMaps maps; - unwindstack::MapInfo* build_id_map_info; - Initialize(state, maps, &build_id_map_info); - - unwindstack::Elf* elf = build_id_map_info->GetElf(std::shared_ptr(), - unwindstack::Regs::CurrentArch()); - if (!elf->valid()) { - state.SkipWithError("Cannot get valid elf from map."); - } - - for (auto _ : state) { - uintptr_t id = build_id_map_info->build_id; - if (id != 0) { - delete reinterpret_cast(id); - build_id_map_info->build_id = 0; - } - benchmark::DoNotOptimize(build_id_map_info->GetBuildID()); - } -} -BENCHMARK(BM_get_build_id_from_elf); - -static void BM_get_build_id_from_file(benchmark::State& state) { - unwindstack::LocalMaps maps; - unwindstack::MapInfo* build_id_map_info; - Initialize(state, maps, &build_id_map_info); - - for (auto _ : state) { - uintptr_t id = build_id_map_info->build_id; - if (id != 0) { - delete reinterpret_cast(id); - build_id_map_info->build_id = 0; - } - benchmark::DoNotOptimize(build_id_map_info->GetBuildID()); - } -} -BENCHMARK(BM_get_build_id_from_file); - BENCHMARK_MAIN();