19 #include <boost/lexical_cast.hpp> 30 using namespace folly;
34 #define FOLLY_RANGE_CHECK_TO_STRING(x) std::string("N/A") 36 #define FOLLY_RANGE_CHECK_TO_STRING(x) std::to_string(x) 40 namespace conv_bench_detail {
64 123456789012345678ULL,
65 1234567890123456789ULL,
66 12345678901234567890ULL,
89 1234567890123456789LL,
110 -12345678901234567LL,
111 -123456789012345678LL,
112 -1234567890123456789LL,
115 #if FOLLY_HAVE_INT128_T 117 unsigned __int128 uint128Num[] = {
119 static_cast<unsigned __int128
>(1) << 0,
120 static_cast<unsigned __int128>(1) << 4,
121 static_cast<unsigned __int128
>(1) << 7,
122 static_cast<unsigned __int128>(1) << 10,
123 static_cast<unsigned __int128
>(1) << 14,
124 static_cast<unsigned __int128>(1) << 17,
125 static_cast<unsigned __int128
>(1) << 20,
126 static_cast<unsigned __int128>(1) << 24,
127 static_cast<unsigned __int128
>(1) << 27,
128 static_cast<unsigned __int128>(1) << 30,
129 static_cast<unsigned __int128
>(1) << 34,
130 static_cast<unsigned __int128>(1) << 37,
131 static_cast<unsigned __int128
>(1) << 40,
132 static_cast<unsigned __int128>(1) << 44,
133 static_cast<unsigned __int128
>(1) << 47,
134 static_cast<unsigned __int128>(1) << 50,
135 static_cast<unsigned __int128
>(1) << 54,
136 static_cast<unsigned __int128>(1) << 57,
137 static_cast<unsigned __int128
>(1) << 60,
138 static_cast<unsigned __int128>(1) << 64,
139 static_cast<unsigned __int128
>(1) << 67,
140 static_cast<unsigned __int128>(1) << 70,
141 static_cast<unsigned __int128
>(1) << 74,
142 static_cast<unsigned __int128>(1) << 77,
143 static_cast<unsigned __int128
>(1) << 80,
144 static_cast<unsigned __int128>(1) << 84,
145 static_cast<unsigned __int128
>(1) << 87,
146 static_cast<unsigned __int128>(1) << 90,
147 static_cast<unsigned __int128
>(1) << 94,
148 static_cast<unsigned __int128>(1) << 97,
149 static_cast<unsigned __int128
>(1) << 100,
150 static_cast<unsigned __int128>(1) << 103,
151 static_cast<unsigned __int128
>(1) << 107,
152 static_cast<unsigned __int128>(1) << 110,
153 static_cast<unsigned __int128
>(1) << 113,
154 static_cast<unsigned __int128>(1) << 117,
155 static_cast<unsigned __int128
>(1) << 120,
156 static_cast<unsigned __int128>(1) << 123,
157 static_cast<unsigned __int128
>(1) << 127,
160 __int128 int128Pos[] = {
162 static_cast<__int128
>(1) << 0,
163 static_cast<__int128>(1) << 4,
164 static_cast<__int128
>(1) << 7,
165 static_cast<__int128>(1) << 10,
166 static_cast<__int128
>(1) << 14,
167 static_cast<__int128>(1) << 17,
168 static_cast<__int128
>(1) << 20,
169 static_cast<__int128>(1) << 24,
170 static_cast<__int128
>(1) << 27,
171 static_cast<__int128>(1) << 30,
172 static_cast<__int128
>(1) << 34,
173 static_cast<__int128>(1) << 37,
174 static_cast<__int128
>(1) << 40,
175 static_cast<__int128>(1) << 44,
176 static_cast<__int128
>(1) << 47,
177 static_cast<__int128>(1) << 50,
178 static_cast<__int128
>(1) << 54,
179 static_cast<__int128>(1) << 57,
180 static_cast<__int128
>(1) << 60,
181 static_cast<__int128>(1) << 64,
182 static_cast<__int128
>(1) << 67,
183 static_cast<__int128>(1) << 70,
184 static_cast<__int128
>(1) << 74,
185 static_cast<__int128>(1) << 77,
186 static_cast<__int128
>(1) << 80,
187 static_cast<__int128>(1) << 84,
188 static_cast<__int128
>(1) << 87,
189 static_cast<__int128>(1) << 90,
190 static_cast<__int128
>(1) << 94,
191 static_cast<__int128>(1) << 97,
192 static_cast<__int128
>(1) << 100,
193 static_cast<__int128>(1) << 103,
194 static_cast<__int128
>(1) << 107,
195 static_cast<__int128>(1) << 110,
196 static_cast<__int128
>(1) << 113,
197 static_cast<__int128>(1) << 117,
198 static_cast<__int128
>(1) << 120,
199 static_cast<__int128>(1) << 123,
200 static_cast<__int128
>(3) << 125,
203 __int128 int128Neg[] = {
205 -(
static_cast<__int128
>(1) << 0),
206 -(
static_cast<__int128
>(1) << 4),
207 -(
static_cast<__int128
>(1) << 7),
208 -(
static_cast<__int128
>(1) << 10),
209 -(
static_cast<__int128
>(1) << 14),
210 -(
static_cast<__int128
>(1) << 17),
211 -(
static_cast<__int128
>(1) << 20),
212 -(
static_cast<__int128
>(1) << 24),
213 -(
static_cast<__int128
>(1) << 27),
214 -(
static_cast<__int128
>(1) << 30),
215 -(
static_cast<__int128
>(1) << 34),
216 -(
static_cast<__int128
>(1) << 37),
217 -(
static_cast<__int128
>(1) << 40),
218 -(
static_cast<__int128
>(1) << 44),
219 -(
static_cast<__int128
>(1) << 47),
220 -(
static_cast<__int128
>(1) << 50),
221 -(
static_cast<__int128
>(1) << 54),
222 -(
static_cast<__int128
>(1) << 57),
223 -(
static_cast<__int128
>(1) << 60),
224 -(
static_cast<__int128
>(1) << 64),
225 -(
static_cast<__int128
>(1) << 67),
226 -(
static_cast<__int128
>(1) << 70),
227 -(
static_cast<__int128
>(1) << 74),
228 -(
static_cast<__int128
>(1) << 77),
229 -(
static_cast<__int128
>(1) << 80),
230 -(
static_cast<__int128
>(1) << 84),
231 -(
static_cast<__int128
>(1) << 87),
232 -(
static_cast<__int128
>(1) << 90),
233 -(
static_cast<__int128
>(1) << 94),
234 -(
static_cast<__int128
>(1) << 97),
235 -(
static_cast<__int128
>(1) << 100),
236 -(
static_cast<__int128
>(1) << 103),
237 -(
static_cast<__int128
>(1) << 107),
238 -(
static_cast<__int128
>(1) << 110),
239 -(
static_cast<__int128
>(1) << 113),
240 -(
static_cast<__int128
>(1) << 117),
241 -(
static_cast<__int128
>(1) << 120),
242 -(
static_cast<__int128
>(1) << 123),
243 -(
static_cast<__int128
>(3) << 125),
254 template <
typename T>
255 void checkArrayIndex(
const T& array,
size_t index) {
256 DCHECK_LT(index,
sizeof(array) /
sizeof(array[0]));
266 bool positive =
true;
270 throw std::runtime_error(
"empty string");
273 while (start < end && isspace(*start)) {
288 while (start < end && *start >=
'0' && *start <=
'9') {
289 auto const newRetVal = retVal * 10 + (*start++ -
'0');
290 if (newRetVal < retVal) {
291 throw std::runtime_error(
"overflow");
297 throw std::runtime_error(
"extra chars at the end");
300 return positive ? retVal : -retVal;
321 assert(*p.end() == 0);
327 assert(*p.end() == 0);
336 static const char digits[201] =
337 "00010203040506070809" 338 "10111213141516171819" 339 "20212223242526272829" 340 "30313233343536373839" 341 "40414243444546474849" 342 "50515253545556575859" 343 "60616263646566676869" 344 "70717273747576777879" 345 "80818283848586878889" 346 "90919293949596979899";
350 while (value >= 100) {
351 auto const i = (value % 100) * 2;
353 dst[
next] = digits[
i + 1];
354 dst[next - 1] = digits[
i];
362 dst[
next] = digits[
i + 1];
363 dst[next - 1] = digits[
i];
378 char*
next = (
char*)dst;
381 *next++ =
'0' + (value % 10);
383 }
while (value != 0);
384 unsigned length = next -
start;
388 while (next > start) {
473 template <
class String>
482 String result = to<String>(
s);
488 template <
class String>
497 String result = to<String>(
s,
nullptr);
504 namespace conv_bench_detail {
512 char otherString[] =
"this is a long string, so it's not so nice";
521 for (
size_t i = 0;
i < n; ++
i) {
533 for (
size_t i = 0;
i < n; ++
i) {
540 namespace conv_bench_detail {
546 -(
static_cast<int8_t>(1) << 4),
547 static_cast<int8_t>(1) << 5,
548 -(static_cast<int8_t>(1) << 6),
553 static_cast<uint8_t>(1) << 5,
558 -(
static_cast<int16_t>(1) << 8),
560 -(static_cast<int16_t>(1) << 14),
565 static_cast<uint16_t>(1) << 12,
570 -(
static_cast<int32_t>(1) << 16),
572 -(static_cast<int32_t>(1) << 30),
577 static_cast<uint32_t>(1) << 25,
582 -(
static_cast<int64_t>(1) << 32),
584 -(static_cast<int64_t>(1) << 62),
589 static_cast<uint64_t>(1) << 50,
596 for (
size_t i = 0;
i < n; ++
i) {
614 for (
size_t i = 0;
i < n; ++
i) {
632 for (
size_t i = 0;
i < n; ++
i) {
650 for (
size_t i = 0;
i < n; ++
i) {
667 #if FOLLY_HAVE_INT128_T 671 -(
static_cast<__int128
>(1) << 2),
672 static_cast<__int128
>(1) << 100,
673 -(static_cast<__int128>(1) << 126),
676 unsigned __int128 u128s[] = {
677 static_cast<unsigned __int128
>(1) << 2,
678 static_cast<unsigned __int128>(1) << 100,
679 static_cast<unsigned __int128
>(1) << 127,
684 for (
size_t i = 0;
i < n; ++
i) {
701 BENCHMARK(preallocateTestNoFloatWithInt128, n) {
702 for (
size_t i = 0;
i < n; ++
i) {
724 #define DEFINE_BENCHMARK_GROUP(n) \ 725 BENCHMARK_PARAM(u64ToAsciiClassicBM, n) \ 726 BENCHMARK_RELATIVE_PARAM(u64ToAsciiTableBM, n) \ 727 BENCHMARK_RELATIVE_PARAM(u64ToAsciiFollyBM, n) \ 728 BENCHMARK_DRAW_LINE() 751 #undef DEFINE_BENCHMARK_GROUP 753 #define DEFINE_BENCHMARK_GROUP(n) \ 754 BENCHMARK_PARAM(u64ToStringClibMeasure, n) \ 755 BENCHMARK_RELATIVE_PARAM(u64ToStringFollyMeasure, n) \ 756 BENCHMARK_RELATIVE_PARAM(i64ToStringFollyMeasurePos, n) \ 757 BENCHMARK_RELATIVE_PARAM(i64ToStringFollyMeasureNeg, n) \ 758 BENCHMARK_DRAW_LINE() 785 #undef DEFINE_BENCHMARK_GROUP 787 #if FOLLY_HAVE_INT128_T 789 void u128ToStringFollyMeasure(
unsigned int n,
size_t index) {
790 checkArrayIndex(uint128Num, index);
796 void i128ToStringFollyMeasurePos(
unsigned int n,
size_t index) {
797 checkArrayIndex(int128Pos, index);
803 void i128ToStringFollyMeasureNeg(
unsigned int n,
size_t index) {
804 checkArrayIndex(int128Neg, index);
810 #define DEFINE_BENCHMARK_GROUP(n) \ 811 BENCHMARK_PARAM(u128ToStringFollyMeasure, n) \ 812 BENCHMARK_RELATIVE_PARAM(i128ToStringFollyMeasurePos, n) \ 813 BENCHMARK_RELATIVE_PARAM(i128ToStringFollyMeasureNeg, n) \ 814 BENCHMARK_DRAW_LINE() 858 #undef DEFINE_BENCHMARK_GROUP 862 #define DEFINE_BENCHMARK_GROUP(n) \ 863 BENCHMARK_PARAM(clibAtoiMeasure, n) \ 864 BENCHMARK_RELATIVE_PARAM(lexicalCastMeasure, n) \ 865 BENCHMARK_RELATIVE_PARAM(handwrittenAtoiMeasure, n) \ 866 BENCHMARK_RELATIVE_PARAM(follyAtoiMeasure, n) \ 867 BENCHMARK_DRAW_LINE() 889 #undef DEFINE_BENCHMARK_GROUP 891 #define DEFINE_BENCHMARK_GROUP(T, n) \ 892 BENCHMARK_PARAM(T##VariadicToBM, n) \ 893 BENCHMARK_RELATIVE_PARAM(T##IdenticalToBM, n) \ 894 BENCHMARK_DRAW_LINE() 903 #undef DEFINE_BENCHMARK_GROUP 907 template <
typename T>
908 inline void stringToTypeClassic(
const char* str,
uint32_t n) {
911 auto val = to<T>(str);
913 }
catch (
const std::exception& e) {
920 template <
typename T>
921 inline void stringToTypeOptional(
const char* str,
uint32_t n) {
923 auto val = tryTo<T>(str);
924 if (
val.hasValue()) {
930 template <
typename T>
936 }
catch (
const std::exception& e) {
943 template <
typename T>
947 if (
val.hasValue()) {
953 constexpr
uint32_t kArithNumIter = 10000;
955 template <
typename T,
typename U>
956 inline size_t arithToArithClassic(
const U* in,
uint32_t numItems) {
958 for (
uint32_t j = 0; j < numItems; ++j) {
960 auto val = to<T>(in[j]);
962 }
catch (
const std::exception& e) {
970 return kArithNumIter * numItems;
973 template <
typename T,
typename U>
974 inline size_t arithToArithOptional(
const U* in,
uint32_t numItems) {
976 for (
uint32_t j = 0; j < numItems; ++j) {
977 auto val = tryTo<T>(*in);
979 if (
val.hasValue()) {
980 auto v2 =
val.value();
988 return kArithNumIter * numItems;
994 namespace conv_bench_detail {
1021 #define STRING_TO_TYPE_BENCHMARK(type, name, pass, fail) \ 1022 BENCHMARK(stringTo##name##Classic, n) { \ 1023 stringToTypeClassic<type>(pass, n); \ 1025 BENCHMARK(stringTo##name##ClassicError, n) { \ 1026 stringToTypeClassic<type>(fail, n); \ 1028 BENCHMARK(stringTo##name##Optional, n) { \ 1029 stringToTypeOptional<type>(pass, n); \ 1031 BENCHMARK(stringTo##name##OptionalError, n) { \ 1032 stringToTypeOptional<type>(fail, n); \ 1035 #define PTR_PAIR_TO_INT_BENCHMARK(type, name, pass, fail) \ 1036 BENCHMARK(ptrPairTo##name##Classic, n) { \ 1037 ptrPairToIntClassic<type>(pass, n); \ 1039 BENCHMARK(ptrPairTo##name##ClassicError, n) { \ 1040 ptrPairToIntClassic<type>(fail, n); \ 1042 BENCHMARK(ptrPairTo##name##Optional, n) { \ 1043 ptrPairToIntOptional<type>(pass, n); \ 1045 BENCHMARK(ptrPairTo##name##OptionalError, n) { \ 1046 ptrPairToIntOptional<type>(fail, n); \ 1049 #define ARITH_TO_ARITH_BENCHMARK(type, name, pass, fail) \ 1050 BENCHMARK_MULTI(name##Classic) { \ 1051 return arithToArithClassic<type>(pass.data(), pass.size()); \ 1053 BENCHMARK_MULTI(name##ClassicError) { \ 1054 return arithToArithClassic<type>(fail.data(), fail.size()); \ 1056 BENCHMARK_MULTI(name##Optional) { \ 1057 return arithToArithOptional<type>(pass.data(), pass.size()); \ 1059 BENCHMARK_MULTI(name##OptionalError) { \ 1060 return arithToArithOptional<type>(fail.data(), fail.size()); \ 1063 #define INT_TO_ARITH_BENCHMARK(type, name, pass, fail) \ 1064 ARITH_TO_ARITH_BENCHMARK(type, intTo##name, pass, fail) 1066 #define FLOAT_TO_ARITH_BENCHMARK(type, name, pass, fail) \ 1067 ARITH_TO_ARITH_BENCHMARK(type, floatTo##name, pass, fail) 1071 BENCHMARK_DRAW_LINE();
1076 BENCHMARK_DRAW_LINE();
1084 " -8123456789123456789 ",
1085 "-10000000000000000000000")
1089 " 18123456789123456789 ",
1091 BENCHMARK_DRAW_LINE();
1100 "10000000000000000000000")
1104 "-8123456789123456789",
1105 "-10000000000000000000000")
1109 "18123456789123456789",
1110 "20000000000000000000")
1111 BENCHMARK_DRAW_LINE();
1117 BENCHMARK_DRAW_LINE();
1119 BENCHMARK_DRAW_LINE();
1121 BENCHMARK_DRAW_LINE();
1124 #undef STRING_TO_TYPE_BENCHMARK 1125 #undef PTR_PAIR_TO_INT_BENCHMARK 1126 #undef ARITH_TO_ARITH_BENCHMARK 1127 #undef INT_TO_ARITH_BENCHMARK 1128 #undef FLOAT_TO_ARITH_BENCHMARK 1131 gflags::ParseCommandLineFlags(&argc, &argv,
true);
std::array< long long, 4 > ll2UintBad
std::vector< uint8_t > buffer(kBufferSize+16)
void i64ToStringFollyMeasurePos(unsigned int n, size_t index)
uint32_t uint64ToBufferUnsafe(uint64_t v, char *const buffer)
unsigned u64ToAsciiClassic(uint64_t value, char *dst)
void clibAtoiMeasure(unsigned int n, unsigned int digits)
#define INT_TO_ARITH_BENCHMARK(type, name, pass, fail)
void i64ToStringFollyMeasureNeg(unsigned int n, size_t index)
std::array< double, 4 > double2FloatBad
std::array< int, 4 > int2UcharGood
static const StringVariadicToBM< fbstring > fbstringVariadicToBM
#define BENCHMARK_SUSPEND
uint32_t digits10(uint64_t v)
std::array< double, 4 > double2IntBad
std::array< double, 4 > double2IntGood
constexpr size_type size() const
void operator()(unsigned int n, size_t len) const
static const StringIdenticalToBM< std::string > stringIdenticalToBM
BENCHMARK_PARAM(u64ToAsciiClassicBM, 1) BENCHMARK_RELATIVE_PARAM(u64ToAsciiTableBM
void u64ToAsciiTableBM(unsigned int n, size_t index)
—— Concurrent Priority Queue Implementation ——
std::array< long long, 4 > ll2SintOrFloatGood
#define DEFINE_BENCHMARK_GROUP(n)
std::array< long long, 4 > ll2UintGood
void follyAtoiMeasure(unsigned int n, unsigned int digits)
void u2aAppendFollyBM(unsigned int n, size_t index)
void u64ToStringClibMeasure(unsigned int n, size_t index)
static int64_t handwrittenAtoi(const char *start, const char *end)
#define FOR_EACH_RANGE(i, begin, end)
#define PTR_PAIR_TO_INT_BENCHMARK(type, name, pass, fail)
constexpr auto size(C const &c) -> decltype(c.size())
int main(int argc, char **argv)
unsigned u64ToAsciiTable(uint64_t value, char *dst)
#define FOLLY_RANGE_CHECK_TO_STRING(x)
BENCHMARK_RELATIVE_PARAM(u64ToAsciiFollyBM, 1) BENCHMARK_DRAW_LINE()
FloatingPoint< float > Float
void u64ToAsciiFollyBM(unsigned int n, size_t index)
std::array< double, 4 > double2FloatGood
auto end(TestAdlIterable &instance)
Range subpiece(size_type first, size_type length=npos) const
std::array< long long, 4 > ll2SintOrFloatBad
static const StringVariadicToBM< std::string > stringVariadicToBM
void handwrittenAtoiMeasure(unsigned int n, unsigned int digits)
std::array< int, 4 > int2ScharGood
static const char *const value
constexpr Iter end() const
constexpr Iter begin() const
void u64ToAsciiClassicBM(unsigned int n, size_t index)
void u2aAppendClassicBM(unsigned int n, size_t index)
void operator()(unsigned int n, size_t len) const
#define FLOAT_TO_ARITH_BENCHMARK(type, name, pass, fail)
void swap(SwapTrackingAlloc< T > &, SwapTrackingAlloc< T > &)
void u64ToStringFollyMeasure(unsigned int n, size_t index)
BENCHMARK(preallocateTestNoFloat, n)
#define STRING_TO_TYPE_BENCHMARK(type, name, pass, fail)
void lexicalCastMeasure(unsigned int n, unsigned int digits)
std::array< int, 4 > int2UcharBad
#define FOLLY_FALLTHROUGH
static const StringIdenticalToBM< fbstring > fbstringIdenticalToBM
auto doNotOptimizeAway(const T &datum) -> typename std::enable_if< !detail::DoNotOptimizeAwayNeedsIndirect< T >::value >::type
std::array< int, 4 > int2ScharBad