Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5133bbfd authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Add new LocalUpdatableMaps benchmarks."

parents 17e8605b 175747fe
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -411,6 +411,7 @@ cc_benchmark {
    srcs: [
        "benchmarks/unwind_benchmarks.cpp",
        "benchmarks/ElfBenchmark.cpp",
        "benchmarks/MapsBenchmark.cpp",
        "benchmarks/SymbolBenchmark.cpp",
        "benchmarks/Utils.cpp",
    ],
+65 −0
Original line number Diff line number Diff line
@@ -23,7 +23,9 @@
#include <benchmark/benchmark.h>

#include <unwindstack/Elf.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>

#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::Memory>(),
                                                    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<std::string*>(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<std::string*>(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);
+93 −0
Original line number Diff line number Diff line
/*
 * 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 <err.h>
#include <stdint.h>

#include <string>

#include <android-base/file.h>
#include <android-base/stringprintf.h>

#include <benchmark/benchmark.h>

#include <unwindstack/Maps.h>

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);
+0 −60
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@

#include <android-base/strings.h>

#include <unwindstack/Elf.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
@@ -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::Memory>(),
                                                    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<std::string*>(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<std::string*>(id);
      build_id_map_info->build_id = 0;
    }
    benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
  }
}
BENCHMARK(BM_get_build_id_from_file);

BENCHMARK_MAIN();