proxygen
ConstexprMathBenchmark.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018-present Facebook, Inc.
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  * http://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 
17 #include <folly/Benchmark.h>
18 #include <folly/ConstexprMath.h>
19 #include <glog/logging.h>
20 #include <limits>
21 #include <type_traits>
22 
23 template <typename ValueT>
25  using UnsignedT = typename std::make_unsigned<ValueT>::type;
26  return static_cast<ValueT>(
27  static_cast<UnsignedT>(a) + static_cast<UnsignedT>(b));
28 }
29 
30 template <typename ValueT>
32  using UnsignedT = typename std::make_unsigned<ValueT>::type;
33  return static_cast<ValueT>(
34  static_cast<UnsignedT>(a) - static_cast<UnsignedT>(b));
35 }
36 
37 template <typename ValueT, typename Op>
38 void Run(size_t iterations, ValueT kMin, ValueT kMax, Op&& op) {
39  auto kMid = (kMin + kMax) / 2;
40 
41  for (size_t round = 0; round < iterations; round++) {
42  for (ValueT a = kMin; a < kMin + 100; a++) {
43  for (ValueT b = kMin; b < kMin + 100; b++) {
44  auto a1 = a, b1 = b;
47  ValueT c = op(a1, b1);
49  }
50  }
51  for (ValueT a = kMin; a < kMin + 100; a++) {
52  for (ValueT b = kMid - 50; b < kMid + 50; b++) {
53  auto a1 = a, b1 = b;
56  ValueT c = op(a1, b1);
58  }
59  }
60  for (ValueT a = kMin; a < kMin + 100; a++) {
61  for (ValueT b = kMax - 100; b < kMax; b++) {
62  auto a1 = a, b1 = b;
65  ValueT c = op(a1, b1);
67  }
68  }
69  for (ValueT a = kMid - 50; a < kMid + 50; a++) {
70  for (ValueT b = kMin; b < kMin + 100; b++) {
71  auto a1 = a, b1 = b;
74  ValueT c = op(a1, b1);
76  }
77  }
78  for (ValueT a = kMid - 50; a < kMid + 50; a++) {
79  for (ValueT b = kMid - 50; b < kMid + 50; b++) {
80  auto a1 = a, b1 = b;
83  ValueT c = op(a1, b1);
85  }
86  }
87  for (ValueT a = kMid - 50; a < kMid + 50; a++) {
88  for (ValueT b = kMax - 100; b < kMax; b++) {
89  auto a1 = a, b1 = b;
92  ValueT c = op(a1, b1);
94  }
95  }
96  for (ValueT a = kMax - 100; a < kMax; a++) {
97  for (ValueT b = kMin; b < kMin + 100; b++) {
98  auto a1 = a, b1 = b;
101  ValueT c = op(a1, b1);
103  }
104  }
105  for (ValueT a = kMax - 100; a < kMax; a++) {
106  for (ValueT b = kMid - 50; b < kMid + 50; b++) {
107  auto a1 = a, b1 = b;
110  ValueT c = op(a1, b1);
112  }
113  }
114  for (ValueT a = kMax - 100; a < kMax; a++) {
115  for (ValueT b = kMax - 100; b < kMax; b++) {
116  auto a1 = a, b1 = b;
119  ValueT c = op(a1, b1);
121  }
122  }
123  }
124 }
125 
126 template <typename ValueT>
127 void Add(size_t iterations, ValueT kMin, ValueT kMax) {
128  Run<ValueT>(iterations, kMin, kMax, [](ValueT a, ValueT b) {
129  return UBSafeAdd(a, b);
130  });
131 }
132 
133 template <typename ValueT>
134 void NoOverflowAdd(size_t iterations, ValueT kMin, ValueT kMax) {
135  Run<ValueT>(iterations, kMin, kMax, [](ValueT a, ValueT b) {
137  });
138 }
139 
140 template <typename ValueT>
141 void Sub(size_t iterations, ValueT kMin, ValueT kMax) {
142  Run<ValueT>(iterations, kMin, kMax, [](ValueT a, ValueT b) {
143  return UBSafeSub(a, b);
144  });
145 }
146 
147 template <typename ValueT>
148 void NoOverflowSub(size_t iterations, ValueT kMin, ValueT kMax) {
149  Run<ValueT>(iterations, kMin, kMax, [](ValueT a, ValueT b) {
151  });
152 }
153 
154 #define GENERATE_BENCHMARKS_FOR_TYPE(ValueT) \
155  BENCHMARK_NAMED_PARAM( \
156  Add, \
157  ValueT, \
158  std::numeric_limits<ValueT>::min(), \
159  std::numeric_limits<ValueT>::max()) \
160  BENCHMARK_RELATIVE_NAMED_PARAM( \
161  NoOverflowAdd, \
162  ValueT, \
163  std::numeric_limits<ValueT>::min(), \
164  std::numeric_limits<ValueT>::max()) \
165  BENCHMARK_NAMED_PARAM( \
166  Sub, \
167  ValueT, \
168  std::numeric_limits<ValueT>::min(), \
169  std::numeric_limits<ValueT>::max()) \
170  BENCHMARK_RELATIVE_NAMED_PARAM( \
171  NoOverflowSub, \
172  ValueT, \
173  std::numeric_limits<ValueT>::min(), \
174  std::numeric_limits<ValueT>::max())
175 
179 BENCHMARK_DRAW_LINE();
181 BENCHMARK_DRAW_LINE();
183 BENCHMARK_DRAW_LINE();
185 BENCHMARK_DRAW_LINE();
187 BENCHMARK_DRAW_LINE();
189 BENCHMARK_DRAW_LINE();
191 
192 int main(int argc, char** argv) {
193  gflags::ParseCommandLineFlags(&argc, &argv, true);
195  return 0;
196 }
constexpr T constexpr_add_overflow_clamped(T a, T b)
char b
void NoOverflowAdd(size_t iterations, ValueT kMin, ValueT kMax)
constexpr To round(std::chrono::duration< Rep, Period > const &d)
Definition: Chrono.h:139
PskType type
char ** argv
#define GENERATE_BENCHMARKS_FOR_TYPE(ValueT)
void Run(size_t iterations, ValueT kMin, ValueT kMax, Op &&op)
constexpr ValueT UBSafeSub(ValueT a, ValueT b)
void runBenchmarks()
Definition: Benchmark.cpp:456
int32_t ValueT
void Sub(size_t iterations, ValueT kMin, ValueT kMax)
int main(void)
Definition: test.c:2834
constexpr T constexpr_sub_overflow_clamped(T a, T b)
char a
constexpr ValueT UBSafeAdd(ValueT a, ValueT b)
void NoOverflowSub(size_t iterations, ValueT kMin, ValueT kMax)
char c
void Add(size_t iterations, ValueT kMin, ValueT kMax)
#define BENCHMARK_DRAW_LINE()
Definition: Benchmark.h:557
auto makeUnpredictable(T &datum) -> typename std::enable_if< !detail::DoNotOptimizeAwayNeedsIndirect< T >::value >::type
Definition: Benchmark.h:285
auto doNotOptimizeAway(const T &datum) -> typename std::enable_if< !detail::DoNotOptimizeAwayNeedsIndirect< T >::value >::type
Definition: Benchmark.h:258