From f5bb60d8e840bd4427783d031301fae51ad26534 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 19 Jul 2022 15:40:09 -0700 Subject: [PATCH] [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 --- BUILD | 9 +- CMakeLists.txt | 31 +++--- build_autogenerated.yaml | 36 ++++--- grpc.gyp | 3 +- .../ext/filters/client_channel/subchannel.cc | 1 + src/core/lib/avl/avl.h | 72 +++++++++----- src/core/lib/channel/channel_args.cc | 30 +----- src/core/lib/channel/channel_args.h | 28 +++++- src/core/lib/gpr/useful.h | 29 ++++++ test/cpp/microbenchmarks/BUILD | 14 +++ test/cpp/microbenchmarks/bm_channel_args.cc | 95 +++++++++++++++++++ .../check_redundant_namespace_qualifiers.py | 2 + 12 files changed, 266 insertions(+), 84 deletions(-) create mode 100644 test/cpp/microbenchmarks/bm_channel_args.cc diff --git a/BUILD b/BUILD index c14200d9509..879aec8d0c4 100644 --- a/BUILD +++ b/BUILD @@ -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( diff --git a/CMakeLists.txt b/CMakeLists.txt index d075ae2ae03..9cad96a12f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index 4c8c0bd7945..d01e0c9c251 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -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 diff --git a/grpc.gyp b/grpc.gyp index d75c4edb714..8a5288ce7ea 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -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', diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index ee9dfcd460b..445d637de5b 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "absl/status/statusor.h" diff --git a/src/core/lib/avl/avl.h b/src/core/lib/avl/avl.h index df4f781c15e..33d2ae661f7 100644 --- a/src/core/lib/avl/avl.h +++ b/src/core/lib/avl/avl.h @@ -22,7 +22,8 @@ #include // IWYU pragma: keep #include #include -#include + +#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 stack_; + IteratorStack stack_; }; explicit AVL(NodePtr root) : root_(std::move(root)) {} diff --git a/src/core/lib/channel/channel_args.cc b/src/core/lib/channel/channel_args.cc index cc73224fff5..d5acbd462b2 100644 --- a/src/core/lib/channel/channel_args.cc +++ b/src/core/lib/channel/channel_args.cc @@ -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); } diff --git a/src/core/lib/channel/channel_args.h b/src/core/lib/channel/channel_args.h index 42db8b69633..157e07072a6 100644 --- a/src/core/lib/channel/channel_args.h +++ b/src/core/lib/channel/channel_args.h @@ -63,6 +63,16 @@ template 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 @@ -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; struct ChannelArgsDeleter { diff --git a/src/core/lib/gpr/useful.h b/src/core/lib/gpr/useful.h index dcd457bcaf4..23d39dc9419 100644 --- a/src/core/lib/gpr/useful.h +++ b/src/core/lib/gpr/useful.h @@ -23,6 +23,9 @@ #include +#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 +int QsortCompare(const absl::variant& a, const absl::variant& 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>(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 +int QsortCompare(const std::pair& a, const std::pair& b) { + const int first = QsortCompare(a.first, b.first); + if (first != 0) return first; + return QsortCompare(a.second, b.second); +} + template constexpr size_t HashPointer(T* p, size_t range) { return (((reinterpret_cast(p)) >> 4) ^ diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD index 259457b0343..371768e73e5 100644 --- a/test/cpp/microbenchmarks/BUILD +++ b/test/cpp/microbenchmarks/BUILD @@ -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, diff --git a/test/cpp/microbenchmarks/bm_channel_args.cc b/test/cpp/microbenchmarks/bm_channel_args.cc new file mode 100644 index 00000000000..a19fdbdce49 --- /dev/null +++ b/test/cpp/microbenchmarks/bm_channel_args.cc @@ -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 + +#include + +#include "absl/container/btree_map.h" + +#include + +#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 m; + std::vector 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 m; + std::vector 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; +} diff --git a/tools/distrib/check_redundant_namespace_qualifiers.py b/tools/distrib/check_redundant_namespace_qualifiers.py index f8f1cb41d49..0241e81d684 100755 --- a/tools/distrib/check_redundant_namespace_qualifiers.py +++ b/tools/distrib/check_redundant_namespace_qualifiers.py @@ -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'])