[channel_args] Improve comparison performance (#30322)

* [channel_args] Improve comparison performance

* fix

* Automated change: Fix sanity tests

* faster still

* fix

* fix

* some no cost boosts if they get hit

* fix

* final tweak for pointers

* check

* fix

* Automated change: Fix sanity tests

* fix

* ugh

Co-authored-by: ctiller <ctiller@users.noreply.github.com>
pull/30354/head
Craig Tiller 3 years ago committed by GitHub
parent 6629f604f9
commit f5bb60d8e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      BUILD
  2. 31
      CMakeLists.txt
  3. 36
      build_autogenerated.yaml
  4. 3
      grpc.gyp
  5. 1
      src/core/ext/filters/client_channel/subchannel.cc
  6. 72
      src/core/lib/avl/avl.h
  7. 30
      src/core/lib/channel/channel_args.cc
  8. 28
      src/core/lib/channel/channel_args.h
  9. 29
      src/core/lib/gpr/useful.h
  10. 14
      test/cpp/microbenchmarks/BUILD
  11. 95
      test/cpp/microbenchmarks/bm_channel_args.cc
  12. 2
      tools/distrib/check_redundant_namespace_qualifiers.py

@ -859,6 +859,10 @@ grpc_cc_library(
grpc_cc_library(
name = "useful",
hdrs = ["src/core/lib/gpr/useful.h"],
external_deps = [
"absl/strings",
"absl/types:variant",
],
language = "c++",
deps = ["gpr_platform"],
)
@ -2187,7 +2191,10 @@ grpc_cc_library(
hdrs = [
"src/core/lib/avl/avl.h",
],
deps = ["gpr_platform"],
deps = [
"gpr_platform",
"useful",
],
)
grpc_cc_library(

31
CMakeLists.txt generated

@ -1579,6 +1579,7 @@ target_link_libraries(gpr
absl::synchronization
absl::time
absl::optional
absl::variant
)
if(_gRPC_PLATFORM_ANDROID)
target_link_libraries(gpr
@ -2372,7 +2373,6 @@ target_link_libraries(grpc
absl::type_traits
absl::statusor
absl::span
absl::variant
absl::utility
gpr
${_gRPC_SSL_LIBRARIES}
@ -2937,7 +2937,6 @@ target_link_libraries(grpc_unsecure
absl::type_traits
absl::statusor
absl::span
absl::variant
absl::utility
gpr
address_sorting
@ -5999,7 +5998,6 @@ target_link_libraries(arena_promise_test
absl::any_invocable
absl::type_traits
absl::statusor
absl::variant
absl::utility
gpr
upb
@ -6275,6 +6273,8 @@ target_include_directories(avl_test
target_link_libraries(avl_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::strings
absl::variant
)
@ -6776,6 +6776,8 @@ target_include_directories(bitset_test
target_link_libraries(bitset_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::strings
absl::variant
)
@ -6918,6 +6920,7 @@ target_link_libraries(call_push_pull_test
absl::type_traits
absl::status
absl::statusor
absl::strings
absl::variant
)
@ -7628,7 +7631,6 @@ target_link_libraries(chunked_vector_test
absl::any_invocable
absl::type_traits
absl::statusor
absl::variant
absl::utility
gpr
upb
@ -9455,7 +9457,6 @@ target_link_libraries(exec_ctx_wakeup_scheduler_test
absl::any_invocable
absl::type_traits
absl::statusor
absl::variant
absl::utility
gpr
upb
@ -9827,7 +9828,6 @@ target_link_libraries(flow_control_test
absl::function_ref
absl::type_traits
absl::statusor
absl::variant
absl::utility
gpr
upb
@ -9892,7 +9892,6 @@ target_link_libraries(for_each_test
absl::hash
absl::type_traits
absl::statusor
absl::variant
absl::utility
gpr
upb
@ -12180,6 +12179,7 @@ target_link_libraries(join_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::type_traits
absl::strings
absl::variant
absl::utility
)
@ -12766,7 +12766,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
absl::any_invocable
absl::type_traits
absl::statusor
absl::variant
absl::utility
gpr
upb
@ -12827,7 +12826,6 @@ target_link_libraries(memory_quota_test
absl::any_invocable
absl::type_traits
absl::statusor
absl::variant
absl::utility
gpr
upb
@ -13867,7 +13865,6 @@ target_link_libraries(pipe_test
absl::any_invocable
absl::type_traits
absl::statusor
absl::variant
absl::utility
gpr
upb
@ -14725,7 +14722,6 @@ target_link_libraries(resource_quota_test
absl::any_invocable
absl::type_traits
absl::statusor
absl::variant
absl::utility
gpr
upb
@ -15919,6 +15915,7 @@ target_link_libraries(single_set_ptr_test
absl::synchronization
absl::time
absl::optional
absl::variant
)
@ -16759,7 +16756,9 @@ target_link_libraries(table_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::type_traits
absl::strings
absl::optional
absl::variant
absl::utility
)
@ -16855,6 +16854,7 @@ target_link_libraries(test_core_event_engine_iomgr_event_engine_timer_heap_test
absl::synchronization
absl::time
absl::optional
absl::variant
)
@ -16949,6 +16949,7 @@ target_link_libraries(test_core_event_engine_iomgr_event_engine_timer_list_test
absl::synchronization
absl::time
absl::optional
absl::variant
)
@ -17110,6 +17111,7 @@ target_link_libraries(test_core_gprpp_time_test
absl::synchronization
absl::time
absl::optional
absl::variant
)
@ -17520,6 +17522,7 @@ target_link_libraries(thread_quota_test
absl::synchronization
absl::time
absl::optional
absl::variant
)
@ -18115,6 +18118,7 @@ target_link_libraries(try_join_test
absl::type_traits
absl::status
absl::statusor
absl::strings
absl::variant
absl::utility
)
@ -18227,6 +18231,7 @@ target_link_libraries(unique_type_name_test
${_gRPC_ALLTARGETS_LIBRARIES}
absl::str_format
absl::strings
absl::variant
)
@ -18333,6 +18338,8 @@ target_include_directories(useful_test
target_link_libraries(useful_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::strings
absl::variant
)
@ -21012,7 +21019,7 @@ generate_pkgconfig(
"gpr"
"gRPC platform support library"
"${gRPC_CORE_VERSION}"
"absl_base absl_cord absl_core_headers absl_memory absl_optional absl_random_random absl_status absl_str_format absl_strings absl_synchronization absl_time"
"absl_base absl_cord absl_core_headers absl_memory absl_optional absl_random_random absl_status absl_str_format absl_strings absl_synchronization absl_time absl_variant"
"-lgpr"
""
"gpr.pc")

@ -281,6 +281,7 @@ libs:
- absl/synchronization:synchronization
- absl/time:time
- absl/types:optional
- absl/types:variant
- name: grpc
build: all
language: c
@ -1690,7 +1691,6 @@ libs:
- absl/meta:type_traits
- absl/status:statusor
- absl/types:span
- absl/types:variant
- absl/utility:utility
- gpr
- libssl
@ -2488,7 +2488,6 @@ libs:
- absl/meta:type_traits
- absl/status:statusor
- absl/types:span
- absl/types:variant
- absl/utility:utility
- gpr
- address_sorting
@ -3965,7 +3964,6 @@ targets:
- absl/functional:any_invocable
- absl/meta:type_traits
- absl/status:statusor
- absl/types:variant
- absl/utility:utility
- gpr
- upb
@ -4045,9 +4043,12 @@ targets:
language: c++
headers:
- src/core/lib/avl/avl.h
- src/core/lib/gpr/useful.h
src:
- test/core/avl/avl_test.cc
deps: []
deps:
- absl/strings:strings
- absl/types:variant
uses_polling: false
- name: aws_request_signer_test
gtest: true
@ -4269,7 +4270,9 @@ targets:
- src/core/lib/gprpp/bitset.h
src:
- test/core/gprpp/bitset_test.cc
deps: []
deps:
- absl/strings:strings
- absl/types:variant
uses_polling: false
- name: byte_buffer_test
gtest: true
@ -4319,6 +4322,7 @@ targets:
- absl/meta:type_traits
- absl/status:status
- absl/status:statusor
- absl/strings:strings
- absl/types:variant
uses_polling: false
- name: cancel_ares_query_test
@ -4595,7 +4599,6 @@ targets:
- absl/functional:any_invocable
- absl/meta:type_traits
- absl/status:statusor
- absl/types:variant
- absl/utility:utility
- gpr
- upb
@ -5292,7 +5295,6 @@ targets:
- absl/functional:any_invocable
- absl/meta:type_traits
- absl/status:statusor
- absl/types:variant
- absl/utility:utility
- gpr
- upb
@ -5532,7 +5534,6 @@ targets:
- absl/functional:function_ref
- absl/meta:type_traits
- absl/status:statusor
- absl/types:variant
- absl/utility:utility
- gpr
- upb
@ -5622,7 +5623,6 @@ targets:
- absl/hash:hash
- absl/meta:type_traits
- absl/status:statusor
- absl/types:variant
- absl/utility:utility
- gpr
- upb
@ -6350,6 +6350,7 @@ targets:
- test/core/promise/join_test.cc
deps:
- absl/meta:type_traits
- absl/strings:strings
- absl/types:variant
- absl/utility:utility
uses_polling: false
@ -6683,7 +6684,6 @@ targets:
- absl/functional:any_invocable
- absl/meta:type_traits
- absl/status:statusor
- absl/types:variant
- absl/utility:utility
- gpr
- upb
@ -6760,7 +6760,6 @@ targets:
- absl/functional:any_invocable
- absl/meta:type_traits
- absl/status:statusor
- absl/types:variant
- absl/utility:utility
- gpr
- upb
@ -7255,7 +7254,6 @@ targets:
- absl/functional:any_invocable
- absl/meta:type_traits
- absl/status:statusor
- absl/types:variant
- absl/utility:utility
- gpr
- upb
@ -7627,7 +7625,6 @@ targets:
- absl/functional:any_invocable
- absl/meta:type_traits
- absl/status:statusor
- absl/types:variant
- absl/utility:utility
- gpr
- upb
@ -8059,6 +8056,7 @@ targets:
- absl/synchronization:synchronization
- absl/time:time
- absl/types:optional
- absl/types:variant
uses_polling: false
- name: sleep_test
gtest: true
@ -8319,7 +8317,9 @@ targets:
- test/core/gprpp/table_test.cc
deps:
- absl/meta:type_traits
- absl/strings:strings
- absl/types:optional
- absl/types:variant
- absl/utility:utility
uses_polling: false
- name: test_core_event_engine_iomgr_event_engine_timer_heap_test
@ -8422,6 +8422,7 @@ targets:
- absl/synchronization:synchronization
- absl/time:time
- absl/types:optional
- absl/types:variant
uses_polling: false
- name: test_core_event_engine_iomgr_event_engine_timer_list_test
gtest: true
@ -8522,6 +8523,7 @@ targets:
- absl/synchronization:synchronization
- absl/time:time
- absl/types:optional
- absl/types:variant
uses_polling: false
- name: test_core_event_engine_slice_buffer_test
gtest: true
@ -8635,6 +8637,7 @@ targets:
- absl/synchronization:synchronization
- absl/time:time
- absl/types:optional
- absl/types:variant
uses_polling: false
- name: test_core_security_credentials_test
gtest: true
@ -8825,6 +8828,7 @@ targets:
- absl/synchronization:synchronization
- absl/time:time
- absl/types:optional
- absl/types:variant
uses_polling: false
- name: thread_stress_test
gtest: true
@ -9076,6 +9080,7 @@ targets:
- absl/meta:type_traits
- absl/status:status
- absl/status:statusor
- absl/strings:strings
- absl/types:variant
- absl/utility:utility
uses_polling: false
@ -9123,6 +9128,7 @@ targets:
deps:
- absl/strings:str_format
- absl/strings:strings
- absl/types:variant
uses_polling: false
- name: unknown_frame_bad_client_test
gtest: true
@ -9154,7 +9160,9 @@ targets:
- src/core/lib/gpr/useful.h
src:
- test/core/gpr/useful_test.cc
deps: []
deps:
- absl/strings:strings
- absl/types:variant
uses_polling: false
- name: varint_test
gtest: true

3
grpc.gyp generated

@ -305,6 +305,7 @@
'absl/synchronization:synchronization',
'absl/time:time',
'absl/types:optional',
'absl/types:variant',
],
'sources': [
'src/core/lib/gpr/alloc.cc',
@ -366,7 +367,6 @@
'absl/meta:type_traits',
'absl/status:statusor',
'absl/types:span',
'absl/types:variant',
'absl/utility:utility',
'gpr',
'address_sorting',
@ -1130,7 +1130,6 @@
'absl/meta:type_traits',
'absl/status:statusor',
'absl/types:span',
'absl/types:variant',
'absl/utility:utility',
'gpr',
'address_sorting',

@ -24,6 +24,7 @@
#include <algorithm>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
#include "absl/status/statusor.h"

@ -22,7 +22,8 @@
#include <algorithm> // IWYU pragma: keep
#include <memory>
#include <utility>
#include <vector>
#include "src/core/lib/gpr/useful.h"
namespace grpc_core {
@ -58,33 +59,32 @@ class AVL {
bool SameIdentity(const AVL& avl) const { return root_ == avl.root_; }
bool operator==(const AVL& other) const {
Iterator a(root_);
Iterator b(other.root_);
friend int QsortCompare(const AVL& left, const AVL& right) {
if (left.root_.get() == right.root_.get()) return 0;
Iterator a(left.root_);
Iterator b(right.root_);
for (;;) {
Node* p = a.current();
Node* q = b.current();
if (p == nullptr) return q == nullptr;
if (q == nullptr) return false;
if (p->kv != q->kv) return false;
if (p != q) {
if (p == nullptr) return -1;
if (q == nullptr) return 1;
const int kv = QsortCompare(p->kv, q->kv);
if (kv != 0) return kv;
} else if (p == nullptr) {
return 0;
}
a.MoveNext();
b.MoveNext();
}
}
bool operator==(const AVL& other) const {
return QsortCompare(*this, other) == 0;
}
bool operator<(const AVL& other) const {
Iterator a(root_);
Iterator b(other.root_);
for (;;) {
Node* p = a.current();
Node* q = b.current();
if (p == nullptr) return q != nullptr;
if (q == nullptr) return false;
if (p->kv < q->kv) return true;
if (p->kv != q->kv) return false;
a.MoveNext();
b.MoveNext();
}
return QsortCompare(*this, other) < 0;
}
private:
@ -104,30 +104,52 @@ class AVL {
};
NodePtr root_;
class IteratorStack {
public:
void Push(Node* n) {
nodes_[depth_] = n;
++depth_;
}
Node* Pop() {
--depth_;
return nodes_[depth_];
}
Node* Back() const { return nodes_[depth_ - 1]; }
bool Empty() const { return depth_ == 0; }
private:
size_t depth_{0};
// 32 is the maximum depth we can accept, and corresponds to ~4billion nodes
// - which ought to suffice our use cases.
Node* nodes_[32];
};
class Iterator {
public:
explicit Iterator(const NodePtr& root) {
auto* n = root.get();
while (n != nullptr) {
stack_.push_back(n);
stack_.Push(n);
n = n->left.get();
}
}
Node* current() const { return stack_.empty() ? nullptr : stack_.back(); }
Node* current() const { return stack_.Empty() ? nullptr : stack_.Back(); }
void MoveNext() {
auto* n = stack_.back();
stack_.pop_back();
auto* n = stack_.Pop();
if (n->right != nullptr) {
n = n->right.get();
while (n != nullptr) {
stack_.push_back(n);
stack_.Push(n);
n = n->left.get();
}
}
}
private:
std::vector<Node*> stack_;
IteratorStack stack_;
};
explicit AVL(NodePtr root) : root_(std::move(root)) {}

@ -41,19 +41,6 @@
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/match.h"
namespace {
int PointerCompare(void* a_ptr, const grpc_arg_pointer_vtable* a_vtable,
void* b_ptr, const grpc_arg_pointer_vtable* b_vtable) {
int c = grpc_core::QsortCompare(a_ptr, b_ptr);
if (c == 0) return 0;
c = grpc_core::QsortCompare(a_vtable, b_vtable);
if (c != 0) return c;
return a_vtable->cmp(a_ptr, b_ptr);
}
} // namespace
namespace grpc_core {
ChannelArgs::Pointer::Pointer(void* p, const grpc_arg_pointer_vtable* vtable)
@ -80,18 +67,6 @@ const grpc_arg_pointer_vtable* ChannelArgs::Pointer::EmptyVTable() {
return &vtable;
}
bool ChannelArgs::Pointer::operator==(const Pointer& rhs) const {
return PointerCompare(p_, vtable_, rhs.p_, rhs.vtable_) == 0;
}
bool ChannelArgs::Pointer::operator<(const Pointer& rhs) const {
return PointerCompare(p_, vtable_, rhs.p_, rhs.vtable_) < 0;
}
bool ChannelArgs::Pointer::operator!=(const Pointer& rhs) const {
return !(*this == rhs);
}
ChannelArgs::ChannelArgs() = default;
ChannelArgs::~ChannelArgs() = default;
ChannelArgs::ChannelArgs(const ChannelArgs& other) = default;
@ -411,8 +386,9 @@ static int cmp_arg(const grpc_arg* a, const grpc_arg* b) {
case GRPC_ARG_INTEGER:
return grpc_core::QsortCompare(a->value.integer, b->value.integer);
case GRPC_ARG_POINTER:
return PointerCompare(a->value.pointer.p, a->value.pointer.vtable,
b->value.pointer.p, b->value.pointer.vtable);
return grpc_core::channel_args_detail::PointerCompare(
a->value.pointer.p, a->value.pointer.vtable, b->value.pointer.p,
b->value.pointer.vtable);
}
GPR_UNREACHABLE_CODE(return 0);
}

@ -63,6 +63,16 @@ template <typename T, typename Ignored = void /* for SFINAE */>
struct ChannelArgTypeTraits;
namespace channel_args_detail {
inline int PointerCompare(void* a_ptr, const grpc_arg_pointer_vtable* a_vtable,
void* b_ptr,
const grpc_arg_pointer_vtable* b_vtable) {
int c = QsortCompare(a_ptr, b_ptr);
if (c == 0) return 0;
c = QsortCompare(a_vtable, b_vtable);
if (c != 0) return c;
return a_vtable->cmp(a_ptr, b_ptr);
}
// The type returned by calling Ref() on a T - used to determine the basest-type
// before the crt refcount base class.
template <typename T>
@ -150,9 +160,20 @@ class ChannelArgs {
return *this;
}
bool operator==(const Pointer& rhs) const;
bool operator<(const Pointer& rhs) const;
bool operator!=(const Pointer& rhs) const;
friend int QsortCompare(const Pointer& a, const Pointer& b) {
return channel_args_detail::PointerCompare(a.p_, a.vtable_, b.p_,
b.vtable_);
}
bool operator==(const Pointer& rhs) const {
return QsortCompare(*this, rhs) == 0;
}
bool operator<(const Pointer& rhs) const {
return QsortCompare(*this, rhs) < 0;
}
bool operator!=(const Pointer& rhs) const {
return QsortCompare(*this, rhs) != 0;
}
void* c_pointer() const { return p_; }
const grpc_arg_pointer_vtable* c_vtable() const { return vtable_; }
@ -163,6 +184,7 @@ class ChannelArgs {
void* p_;
const grpc_arg_pointer_vtable* vtable_;
};
using Value = absl::variant<int, std::string, Pointer>;
struct ChannelArgsDeleter {

@ -23,6 +23,9 @@
#include <cstddef>
#include "absl/strings/string_view.h"
#include "absl/types/variant.h"
/** useful utilities that don't belong anywhere else */
namespace grpc_core {
@ -98,6 +101,32 @@ int QsortCompare(const T& a, const T& b) {
return 0;
}
template <typename... X>
int QsortCompare(const absl::variant<X...>& a, const absl::variant<X...>& b) {
const int index = QsortCompare(a.index(), b.index());
if (index != 0) return index;
return absl::visit(
[&](const auto& x) {
return QsortCompare(x, absl::get<absl::remove_cvref_t<decltype(x)>>(b));
},
a);
}
inline int QsortCompare(absl::string_view a, absl::string_view b) {
return a.compare(b);
}
inline int QsortCompare(const std::string& a, const std::string& b) {
return a.compare(b);
}
template <typename A, typename B>
int QsortCompare(const std::pair<A, B>& a, const std::pair<A, B>& b) {
const int first = QsortCompare(a.first, b.first);
if (first != 0) return first;
return QsortCompare(a.second, b.second);
}
template <typename T>
constexpr size_t HashPointer(T* p, size_t range) {
return (((reinterpret_cast<size_t>(p)) >> 4) ^

@ -28,6 +28,20 @@ grpc_cc_test(
deps = ["//test/core/util:grpc_test_util"],
)
grpc_cc_test(
name = "bm_channel_args",
srcs = ["bm_channel_args.cc"],
external_deps = [
"benchmark",
"absl/container:btree",
],
deps = [
"//:channel_args",
"//:grpc++",
"//test/core/util:grpc_test_util",
],
)
grpc_cc_library(
name = "helpers",
testonly = 1,

@ -0,0 +1,95 @@
// Copyright 2017 gRPC authors.
//
// 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.
/* Benchmark ChannelArgs comparison performance between grpc_channel_args and
* grpc_core::ChannelArgs */
#include <random>
#include <benchmark/benchmark.h>
#include "absl/container/btree_map.h"
#include <grpcpp/support/channel_arguments.h>
#include "src/core/lib/channel/channel_args.h"
const char kKey[] = "a very long key";
const char kValue[] = "a very long value";
void BM_ChannelArgs(benchmark::State& state) {
grpc_core::ChannelArgs arg1, arg2;
arg1 = arg1.Set(kKey, kValue);
arg2 = arg2.Set(kKey, kValue);
for (auto s : state) {
benchmark::DoNotOptimize(arg1 < arg2);
}
}
BENCHMARK(BM_ChannelArgs);
void BM_grpc_channel_args(benchmark::State& state) {
grpc_channel_args arg1, arg2;
grpc::ChannelArguments xargs;
xargs.SetString(kKey, kValue);
xargs.SetChannelArgs(&arg1);
xargs.SetChannelArgs(&arg2);
for (auto s : state) {
benchmark::DoNotOptimize(grpc_channel_args_compare(&arg1, &arg2));
}
}
BENCHMARK(BM_grpc_channel_args);
void BM_ChannelArgsAsKeyIntoMap(benchmark::State& state) {
std::map<grpc_core::ChannelArgs, int> m;
std::vector<grpc_core::ChannelArgs> v;
for (int i = 0; i < 10000; i++) {
const auto& a = grpc_core::ChannelArgs().Set(kKey, i);
m[a] = i;
v.push_back(a);
}
std::shuffle(v.begin(), v.end(), std::mt19937(std::random_device()()));
size_t n = 0;
for (auto s : state) {
benchmark::DoNotOptimize(m.find(v[n++ % v.size()]));
}
}
BENCHMARK(BM_ChannelArgsAsKeyIntoMap);
void BM_ChannelArgsAsKeyIntoBTree(benchmark::State& state) {
absl::btree_map<grpc_core::ChannelArgs, int> m;
std::vector<grpc_core::ChannelArgs> v;
for (int i = 0; i < 10000; i++) {
const auto& a = grpc_core::ChannelArgs().Set(kKey, i);
m[a] = i;
v.push_back(a);
}
std::shuffle(v.begin(), v.end(), std::mt19937(std::random_device()()));
size_t n = 0;
for (auto s : state) {
benchmark::DoNotOptimize(m.find(v[n++ % v.size()]));
}
}
BENCHMARK(BM_ChannelArgsAsKeyIntoBTree);
// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
// and others do not. This allows us to support both modes.
namespace benchmark {
void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
} // namespace benchmark
int main(int argc, char** argv) {
::benchmark::Initialize(&argc, argv);
benchmark::RunTheBenchmarksNamespaced();
return 0;
}

@ -118,6 +118,7 @@ namespace bar {
namespace foo {}
namespace foo {
foo::a;
::foo::a;
}
"""
_TEST_EXPECTED = """
@ -128,6 +129,7 @@ namespace bar {
namespace foo {}
namespace foo {
a;
::foo::a;
}
"""
output = update_file(_TEST, ['foo'])

Loading…
Cancel
Save