abseil-cpp/absl/flags/flag_benchmark.cc
Go to the documentation of this file.
1 //
2 // Copyright 2020 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include <stdint.h>
17 
18 #include <string>
19 #include <vector>
20 
21 #include "absl/flags/flag.h"
22 #include "absl/flags/marshalling.h"
23 #include "absl/flags/parse.h"
24 #include "absl/flags/reflection.h"
25 #include "absl/strings/string_view.h"
26 #include "absl/time/time.h"
27 #include "absl/types/optional.h"
28 #include "benchmark/benchmark.h"
29 
30 namespace {
31 using String = std::string;
32 using VectorOfStrings = std::vector<std::string>;
33 using AbslDuration = absl::Duration;
34 
35 // We do not want to take over marshalling for the types absl::optional<int>,
36 // absl::optional<std::string> which we do not own. Instead we introduce unique
37 // "aliases" to these types, which we do.
38 using AbslOptionalInt = absl::optional<int>;
39 struct OptionalInt : AbslOptionalInt {
40  using AbslOptionalInt::AbslOptionalInt;
41 };
42 // Next two functions represent Abseil Flags marshalling for OptionalInt.
43 bool AbslParseFlag(absl::string_view src, OptionalInt* flag,
44  std::string* error) {
45  int val;
46  if (src.empty())
47  flag->reset();
48  else if (!absl::ParseFlag(src, &val, error))
49  return false;
50  *flag = val;
51  return true;
52 }
53 std::string AbslUnparseFlag(const OptionalInt& flag) {
54  return !flag ? "" : absl::UnparseFlag(*flag);
55 }
56 
57 using AbslOptionalString = absl::optional<std::string>;
58 struct OptionalString : AbslOptionalString {
59  using AbslOptionalString::AbslOptionalString;
60 };
61 // Next two functions represent Abseil Flags marshalling for OptionalString.
62 bool AbslParseFlag(absl::string_view src, OptionalString* flag,
63  std::string* error) {
64  std::string val;
65  if (src.empty())
66  flag->reset();
67  else if (!absl::ParseFlag(src, &val, error))
68  return false;
69  *flag = val;
70  return true;
71 }
72 std::string AbslUnparseFlag(const OptionalString& flag) {
73  return !flag ? "" : absl::UnparseFlag(*flag);
74 }
75 
76 struct UDT {
77  UDT() = default;
78  UDT(const UDT&) {}
79  UDT& operator=(const UDT&) { return *this; }
80 };
81 // Next two functions represent Abseil Flags marshalling for UDT.
82 bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
83 std::string AbslUnparseFlag(const UDT&) { return ""; }
84 
85 } // namespace
86 
87 #define BENCHMARKED_TYPES(A) \
88  A(bool) \
89  A(int16_t) \
90  A(uint16_t) \
91  A(int32_t) \
92  A(uint32_t) \
93  A(int64_t) \
94  A(uint64_t) \
95  A(double) \
96  A(float) \
97  A(String) \
98  A(VectorOfStrings) \
99  A(OptionalInt) \
100  A(OptionalString) \
101  A(AbslDuration) \
102  A(UDT)
103 
104 #define REPLICATE_0(A, T, name, index) A(T, name, index)
105 #define REPLICATE_1(A, T, name, index) \
106  REPLICATE_0(A, T, name, index##0) REPLICATE_0(A, T, name, index##1)
107 #define REPLICATE_2(A, T, name, index) \
108  REPLICATE_1(A, T, name, index##0) REPLICATE_1(A, T, name, index##1)
109 #define REPLICATE_3(A, T, name, index) \
110  REPLICATE_2(A, T, name, index##0) REPLICATE_2(A, T, name, index##1)
111 #define REPLICATE_4(A, T, name, index) \
112  REPLICATE_3(A, T, name, index##0) REPLICATE_3(A, T, name, index##1)
113 #define REPLICATE_5(A, T, name, index) \
114  REPLICATE_4(A, T, name, index##0) REPLICATE_4(A, T, name, index##1)
115 #define REPLICATE_6(A, T, name, index) \
116  REPLICATE_5(A, T, name, index##0) REPLICATE_5(A, T, name, index##1)
117 #define REPLICATE_7(A, T, name, index) \
118  REPLICATE_6(A, T, name, index##0) REPLICATE_6(A, T, name, index##1)
119 #define REPLICATE_8(A, T, name, index) \
120  REPLICATE_7(A, T, name, index##0) REPLICATE_7(A, T, name, index##1)
121 #define REPLICATE_9(A, T, name, index) \
122  REPLICATE_8(A, T, name, index##0) REPLICATE_8(A, T, name, index##1)
123 #if defined(_MSC_VER)
124 #define REPLICATE(A, T, name) \
125  REPLICATE_7(A, T, name, 0) REPLICATE_7(A, T, name, 1)
126 #define SINGLE_FLAG(T) FLAGS_##T##_flag_00000000
127 #else
128 #define REPLICATE(A, T, name) \
129  REPLICATE_9(A, T, name, 0) REPLICATE_9(A, T, name, 1)
130 #define SINGLE_FLAG(T) FLAGS_##T##_flag_0000000000
131 #endif
132 #define REPLICATE_ALL(A, T, name) \
133  REPLICATE_9(A, T, name, 0) REPLICATE_9(A, T, name, 1)
134 
135 #define COUNT(T, name, index) +1
136 constexpr size_t kNumFlags = 0 REPLICATE(COUNT, _, _);
137 
138 #if defined(__clang__) && defined(__linux__)
139 // Force the flags used for benchmarks into a separate ELF section.
140 // This ensures that, even when other parts of the code might change size,
141 // the layout of the flags across cachelines is kept constant. This makes
142 // benchmark results more reproducible across unrelated code changes.
143 #pragma clang section data = ".benchmark_flags"
144 #endif
145 #define DEFINE_FLAG(T, name, index) ABSL_FLAG(T, name##_##index, {}, "");
146 #define FLAG_DEF(T) REPLICATE(DEFINE_FLAG, T, T##_flag);
148 #if defined(__clang__) && defined(__linux__)
149 #pragma clang section data = ""
150 #endif
151 // Register thousands of flags to bloat up the size of the registry.
152 // This mimics real life production binaries.
153 #define BLOAT_FLAG(_unused1, _unused2, index) \
154  ABSL_FLAG(int, bloat_flag_##index, 0, "");
156 
157 namespace {
158 
159 #define FLAG_PTR(T, name, index) &FLAGS_##name##_##index,
160 #define FLAG_PTR_ARR(T) \
161  static constexpr absl::Flag<T>* FlagPtrs_##T[] = { \
162  REPLICATE(FLAG_PTR, T, T##_flag)};
164 
165 #define BM_SingleGetFlag(T) \
166  void BM_SingleGetFlag_##T(benchmark::State& state) { \
167  for (auto _ : state) { \
168  benchmark::DoNotOptimize(absl::GetFlag(SINGLE_FLAG(T))); \
169  } \
170  } \
171  BENCHMARK(BM_SingleGetFlag_##T)->ThreadRange(1, 16);
172 
174 
175 template <typename T>
176 struct Accumulator {
177  using type = T;
178 };
179 template <>
180 struct Accumulator<String> {
181  using type = size_t;
182 };
183 template <>
184 struct Accumulator<VectorOfStrings> {
185  using type = size_t;
186 };
187 template <>
188 struct Accumulator<OptionalInt> {
189  using type = bool;
190 };
191 template <>
192 struct Accumulator<OptionalString> {
193  using type = bool;
194 };
195 template <>
196 struct Accumulator<UDT> {
197  using type = bool;
198 };
199 
200 template <typename T>
201 void Accumulate(typename Accumulator<T>::type& a, const T& f) {
202  a += f;
203 }
204 void Accumulate(bool& a, bool f) { a = a || f; }
205 void Accumulate(size_t& a, const std::string& f) { a += f.size(); }
206 void Accumulate(size_t& a, const std::vector<std::string>& f) { a += f.size(); }
207 void Accumulate(bool& a, const OptionalInt& f) { a |= f.has_value(); }
208 void Accumulate(bool& a, const OptionalString& f) { a |= f.has_value(); }
209 void Accumulate(bool& a, const UDT& f) {
210  a |= reinterpret_cast<int64_t>(&f) & 0x1;
211 }
212 
213 #define BM_ManyGetFlag(T) \
214  void BM_ManyGetFlag_##T(benchmark::State& state) { \
215  Accumulator<T>::type res = {}; \
216  while (state.KeepRunningBatch(kNumFlags)) { \
217  for (auto* flag_ptr : FlagPtrs_##T) { \
218  Accumulate(res, absl::GetFlag(*flag_ptr)); \
219  } \
220  } \
221  benchmark::DoNotOptimize(res); \
222  } \
223  BENCHMARK(BM_ManyGetFlag_##T)->ThreadRange(1, 8);
224 
226 
227 void BM_ThreadedFindCommandLineFlag(benchmark::State& state) {
228  char dummy[] = "dummy";
229  char* argv[] = {dummy};
230  // We need to ensure that flags have been parsed. That is where the registry
231  // is finalized.
232  absl::ParseCommandLine(1, argv);
233 
234  while (state.KeepRunningBatch(kNumFlags)) {
235  for (auto* flag_ptr : FlagPtrs_bool) {
237  }
238  }
239 }
240 BENCHMARK(BM_ThreadedFindCommandLineFlag)->ThreadRange(1, 16);
241 
242 } // namespace
243 
244 #define InvokeGetFlag(T) \
245  T AbslInvokeGetFlag##T() { return absl::GetFlag(SINGLE_FLAG(T)); } \
246  int odr##T = (benchmark::DoNotOptimize(AbslInvokeGetFlag##T), 1);
247 
249 
250 // To veiw disassembly use: gdb ${BINARY} -batch -ex "disassemble /s $FUNC"
flag
uint32_t flag
Definition: ssl_versions.cc:162
UDT::operator=
UDT & operator=(const UDT &)=default
absl::ParseFlag
ABSL_NAMESPACE_BEGIN bool ParseFlag(absl::string_view input, T *dst, std::string *error)
Definition: abseil-cpp/absl/flags/marshalling.h:328
bool
bool
Definition: setup_once.h:312
BM_ManyGetFlag
#define BM_ManyGetFlag(T)
Definition: abseil-cpp/absl/flags/flag_benchmark.cc:213
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
FLAG_PTR_ARR
#define FLAG_PTR_ARR(T)
Definition: abseil-cpp/absl/flags/flag_benchmark.cc:160
absl::ParseCommandLine
std::vector< char * > ParseCommandLine(int argc, char *argv[])
Definition: abseil-cpp/absl/flags/parse.cc:815
COUNT
#define COUNT(T, name, index)
Definition: abseil-cpp/absl/flags/flag_benchmark.cc:135
absl::FindCommandLineFlag
CommandLineFlag * FindCommandLineFlag(absl::string_view name)
Definition: abseil-cpp/absl/flags/reflection.cc:336
benchmark::DoNotOptimize
BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const &value)
Definition: benchmark/include/benchmark/benchmark.h:375
absl::UnparseFlag
std::string UnparseFlag(const T &v)
Definition: abseil-cpp/absl/flags/marshalling.h:342
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
BM_SingleGetFlag
#define BM_SingleGetFlag(T)
Definition: abseil-cpp/absl/flags/flag_benchmark.cc:165
T
#define T(upbtypeconst, upbtype, ctype, default_value)
BENCHMARKED_TYPES
#define BENCHMARKED_TYPES(A)
Definition: abseil-cpp/absl/flags/flag_benchmark.cc:87
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
AbslUnparseFlag
std::string AbslUnparseFlag(const UDT &)
Definition: bloaty/third_party/abseil-cpp/absl/flags/internal/usage_test.cc:50
UDT::UDT
UDT()=default
BLOAT_FLAG
#define BLOAT_FLAG(_unused1, _unused2, index)
Definition: abseil-cpp/absl/flags/flag_benchmark.cc:153
gmock_output_test._
_
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
absl::optional
Definition: abseil-cpp/absl/types/internal/optional.h:61
kNumFlags
constexpr size_t kNumFlags
Definition: abseil-cpp/absl/flags/flag_benchmark.cc:136
InvokeGetFlag
#define InvokeGetFlag(T)
Definition: abseil-cpp/absl/flags/flag_benchmark.cc:244
FLAG_DEF
#define FLAG_DEF(T)
Definition: abseil-cpp/absl/flags/flag_benchmark.cc:146
stdint.h
benchmark::State
Definition: benchmark/include/benchmark/benchmark.h:503
AbslParseFlag
bool AbslParseFlag(absl::string_view, UDT *, std::string *)
Definition: bloaty/third_party/abseil-cpp/absl/flags/internal/usage_test.cc:49
state
Definition: bloaty/third_party/zlib/contrib/blast/blast.c:41
absl::ABSL_NAMESPACE_BEGIN::dummy
int dummy
Definition: function_type_benchmark.cc:28
REPLICATE
#define REPLICATE(A, T, name)
Definition: abseil-cpp/absl/flags/flag_benchmark.cc:128
REPLICATE_ALL
#define REPLICATE_ALL(A, T, name)
Definition: abseil-cpp/absl/flags/flag_benchmark.cc:132
absl::string_view::empty
constexpr bool empty() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:292
BENCHMARK
#define BENCHMARK(n)
Definition: benchmark/include/benchmark/benchmark.h:1170
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
Duration
struct Duration Duration
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:640


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:24