tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

vlog_config_benchmark.cc (7359B)


      1 // Copyright 2022 The Abseil Authors
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include <algorithm>
     16 #include <atomic>
     17 #include <cstddef>
     18 #include <cstring>
     19 #include <memory>
     20 #include <new>
     21 #include <random>
     22 #include <string>
     23 #include <type_traits>
     24 #include <utility>
     25 #include <vector>
     26 
     27 #include "absl/base/config.h"
     28 #include "absl/container/internal/layout.h"
     29 #include "absl/log/internal/vlog_config.h"
     30 #include "absl/memory/memory.h"
     31 #include "absl/random/distributions.h"
     32 #include "absl/strings/str_cat.h"
     33 #include "benchmark/benchmark.h"
     34 
     35 namespace absl {
     36 ABSL_NAMESPACE_BEGIN
     37 namespace log_internal {
     38 // Performance of `UpdateLogSites` depends upon the number and organization of
     39 // `VLogSite`s in the program.  We can synthesize some on the heap to mimic
     40 // their layout and linkage in static data.
     41 class SyntheticBinary {
     42 public:
     43  explicit SyntheticBinary(const size_t num_tus,
     44                           const size_t max_extra_static_data_bytes_per_tu,
     45                           const size_t max_sites_per_tu,
     46                           const int num_shuffles) {
     47    per_tu_data_.reserve(num_tus);
     48    auto sites = absl::make_unique<VLogSite *[]>(num_tus * max_sites_per_tu);
     49    for (size_t i = 0; i < num_tus; i++) {
     50      const std::string filename =
     51          absl::StrCat("directory-", i / 100, "/subdirectory-", i % 100 / 10,
     52                       "/file-", i % 10, ".cc");
     53      container_internal::Layout<char, VLogSite, char> layout(
     54          filename.size() + 1,
     55          absl::LogUniform<size_t>(bitgen_, 1, max_sites_per_tu),
     56          absl::LogUniform<size_t>(bitgen_, 0,
     57                                   max_extra_static_data_bytes_per_tu));
     58      auto buf = absl::make_unique<char[]>(layout.AllocSize());
     59      layout.PoisonPadding(buf.get());
     60      memcpy(layout.Pointer<0>(buf.get()), filename.c_str(),
     61             filename.size() + 1);
     62      for (VLogSite &site : layout.Slice<1>(buf.get())) {
     63        sites[num_sites_++] =
     64            new (&site) VLogSite(layout.Pointer<0>(buf.get()));
     65        // The last one is a dangling pointer but will be fixed below.
     66        site.next_.store(&site + 1, std::memory_order_seq_cst);
     67      }
     68      num_extra_static_data_bytes_ += layout.Size<2>();
     69      per_tu_data_.push_back(PerTU{layout, std::move(buf)});
     70    }
     71    // Now link the files together back-to-front into a circular list.
     72    for (size_t i = 0; i < num_tus; i++) {
     73      auto &tu = per_tu_data_[i];
     74      auto &next_tu = per_tu_data_[(i + 1) % num_tus];
     75      tu.layout.Slice<1>(tu.buf.get())
     76          .back()
     77          .next_.store(next_tu.layout.Pointer<1>(next_tu.buf.get()),
     78                       std::memory_order_seq_cst);
     79    }
     80    // Now do some shufflin'.
     81    auto new_sites = absl::make_unique<VLogSite *[]>(num_sites_);
     82    for (int shuffle_num = 0; shuffle_num < num_shuffles; shuffle_num++) {
     83      // Each shuffle cuts the ring into three pieces and rearranges them.
     84      const size_t cut_a = absl::Uniform(bitgen_, size_t{0}, num_sites_);
     85      const size_t cut_b = absl::Uniform(bitgen_, size_t{0}, num_sites_);
     86      const size_t cut_c = absl::Uniform(bitgen_, size_t{0}, num_sites_);
     87      if (cut_a == cut_b || cut_b == cut_c || cut_a == cut_c) continue;
     88      // The same cuts, sorted:
     89      const size_t cut_1 = std::min({cut_a, cut_b, cut_c});
     90      const size_t cut_3 = std::max({cut_a, cut_b, cut_c});
     91      const size_t cut_2 = cut_a ^ cut_b ^ cut_c ^ cut_1 ^ cut_3;
     92      VLogSite *const tmp = sites[cut_1]->next_.load(std::memory_order_seq_cst);
     93      sites[cut_1]->next_.store(
     94          sites[cut_2]->next_.load(std::memory_order_seq_cst),
     95          std::memory_order_seq_cst);
     96      sites[cut_2]->next_.store(
     97          sites[cut_3]->next_.load(std::memory_order_seq_cst),
     98          std::memory_order_seq_cst);
     99      sites[cut_3]->next_.store(tmp, std::memory_order_seq_cst);
    100      memcpy(&new_sites[0], &sites[0], sizeof(VLogSite *) * (cut_1 + 1));
    101      memcpy(&new_sites[cut_1 + 1], &sites[cut_2 + 1],
    102             sizeof(VLogSite *) * (cut_3 - cut_2));
    103      memcpy(&new_sites[cut_1 + 1 + cut_3 - cut_2], &sites[cut_1 + 1],
    104             sizeof(VLogSite *) * (cut_2 - cut_1));
    105      memcpy(&new_sites[cut_3 + 1], &sites[cut_3 + 1],
    106             sizeof(VLogSite *) * (num_sites_ - cut_3 - 1));
    107      sites.swap(new_sites);
    108    }
    109    const char *last_file = nullptr;
    110    for (size_t i = 0; i < num_sites_; i++) {
    111      if (sites[i]->file_ == last_file) continue;
    112      last_file = sites[i]->file_;
    113      num_new_files_++;
    114    }
    115    absl::log_internal::SetVModuleListHeadForTestOnly(sites[0]);
    116    sites[num_tus - 1]->next_.store(nullptr, std::memory_order_seq_cst);
    117  }
    118  ~SyntheticBinary() {
    119    static_assert(std::is_trivially_destructible<VLogSite>::value, "");
    120    absl::log_internal::SetVModuleListHeadForTestOnly(nullptr);
    121  }
    122 
    123  size_t num_sites() const { return num_sites_; }
    124  size_t num_new_files() const { return num_new_files_; }
    125  size_t num_extra_static_data_bytes() const {
    126    return num_extra_static_data_bytes_;
    127  }
    128 
    129 private:
    130  struct PerTU {
    131    container_internal::Layout<char, VLogSite, char> layout;
    132    std::unique_ptr<char[]> buf;
    133  };
    134 
    135  std::mt19937 bitgen_;
    136  std::vector<PerTU> per_tu_data_;
    137  size_t num_sites_ = 0;
    138  size_t num_new_files_ = 0;
    139  size_t num_extra_static_data_bytes_ = 0;
    140 };
    141 
    142 namespace {
    143 void BM_UpdateVModuleEmpty(benchmark::State& state) {
    144  SyntheticBinary bin(static_cast<size_t>(state.range(0)), 10 * 1024 * 1024,
    145                      256, state.range(1));
    146  for (auto s : state) {
    147    absl::log_internal::UpdateVModule("");
    148  }
    149  state.SetItemsProcessed(static_cast<int>(bin.num_new_files()));
    150 }
    151 BENCHMARK(BM_UpdateVModuleEmpty)
    152    ->ArgPair(100, 200)
    153    ->ArgPair(1000, 2000)
    154    ->ArgPair(10000, 20000);
    155 
    156 void BM_UpdateVModuleShort(benchmark::State& state) {
    157  SyntheticBinary bin(static_cast<size_t>(state.range(0)), 10 * 1024 * 1024,
    158                      256, state.range(1));
    159  for (auto s : state) {
    160    absl::log_internal::UpdateVModule("directory2/*=4");
    161  }
    162  state.SetItemsProcessed(static_cast<int>(bin.num_new_files()));
    163 }
    164 BENCHMARK(BM_UpdateVModuleShort)
    165    ->ArgPair(100, 200)
    166    ->ArgPair(1000, 2000)
    167    ->ArgPair(10000, 20000);
    168 
    169 void BM_UpdateVModuleLong(benchmark::State& state) {
    170  SyntheticBinary bin(static_cast<size_t>(state.range(0)), 10 * 1024 * 1024,
    171                      256, state.range(1));
    172  for (auto s : state) {
    173    absl::log_internal::UpdateVModule(
    174        "d?r?c?o?y2/*=4,d?*r?*c?**o?*y1/*=2,d?*rc?**o?*y3/*=2,,"
    175        "d?*r?*c?**o?*1/*=1,d?*r?**o?*y1/*=2,d?*r???***y1/*=7,"
    176        "d?*r?**o?*y1/aaa=6");
    177  }
    178  state.SetItemsProcessed(static_cast<int>(bin.num_new_files()));
    179 }
    180 BENCHMARK(BM_UpdateVModuleLong)
    181    ->ArgPair(100, 200)
    182    ->ArgPair(1000, 2000)
    183    ->ArgPair(10000, 20000);
    184 }  // namespace
    185 }  // namespace log_internal
    186 ABSL_NAMESPACE_END
    187 }  // namespace absl