123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134 |
- /*
- * Copyright 2016-present Facebook, Inc.
- *
- * 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.
- */
- #include <folly/Conv.h>
- #include <boost/lexical_cast.hpp>
- #include <folly/Benchmark.h>
- #include <folly/CppAttributes.h>
- #include <folly/container/Foreach.h>
- #include <array>
- #include <limits>
- #include <stdexcept>
- using namespace std;
- using namespace folly;
- // Android doesn't support std::to_string so just use a placeholder there.
- #ifdef __ANDROID__
- #define FOLLY_RANGE_CHECK_TO_STRING(x) std::string("N/A")
- #else
- #define FOLLY_RANGE_CHECK_TO_STRING(x) std::to_string(x)
- #endif
- namespace folly {
- namespace conv_bench_detail {
- // Keep this data global and non-const, so the compiler cannot make
- // any assumptions about the actual values at compile time
- uint64_t uint64Num[] = {
- 0,
- 1ULL,
- 12ULL,
- 123ULL,
- 1234ULL,
- 12345ULL,
- 123456ULL,
- 1234567ULL,
- 12345678ULL,
- 123456789ULL,
- 1234567890ULL,
- 12345678901ULL,
- 123456789012ULL,
- 1234567890123ULL,
- 12345678901234ULL,
- 123456789012345ULL,
- 1234567890123456ULL,
- 12345678901234567ULL,
- 123456789012345678ULL,
- 1234567890123456789ULL,
- 12345678901234567890ULL,
- };
- int64_t int64Pos[] = {
- 0,
- 1LL,
- 12LL,
- 123LL,
- 1234LL,
- 12345LL,
- 123456LL,
- 1234567LL,
- 12345678LL,
- 123456789LL,
- 1234567890LL,
- 12345678901LL,
- 123456789012LL,
- 1234567890123LL,
- 12345678901234LL,
- 123456789012345LL,
- 1234567890123456LL,
- 12345678901234567LL,
- 123456789012345678LL,
- 1234567890123456789LL,
- };
- int64_t int64Neg[] = {
- 0,
- -1LL,
- -12LL,
- -123LL,
- -1234LL,
- -12345LL,
- -123456LL,
- -1234567LL,
- -12345678LL,
- -123456789LL,
- -1234567890LL,
- -12345678901LL,
- -123456789012LL,
- -1234567890123LL,
- -12345678901234LL,
- -123456789012345LL,
- -1234567890123456LL,
- -12345678901234567LL,
- -123456789012345678LL,
- -1234567890123456789LL,
- };
- #if FOLLY_HAVE_INT128_T
- unsigned __int128 uint128Num[] = {
- 0,
- static_cast<unsigned __int128>(1) << 0,
- static_cast<unsigned __int128>(1) << 4,
- static_cast<unsigned __int128>(1) << 7,
- static_cast<unsigned __int128>(1) << 10,
- static_cast<unsigned __int128>(1) << 14,
- static_cast<unsigned __int128>(1) << 17,
- static_cast<unsigned __int128>(1) << 20,
- static_cast<unsigned __int128>(1) << 24,
- static_cast<unsigned __int128>(1) << 27,
- static_cast<unsigned __int128>(1) << 30,
- static_cast<unsigned __int128>(1) << 34,
- static_cast<unsigned __int128>(1) << 37,
- static_cast<unsigned __int128>(1) << 40,
- static_cast<unsigned __int128>(1) << 44,
- static_cast<unsigned __int128>(1) << 47,
- static_cast<unsigned __int128>(1) << 50,
- static_cast<unsigned __int128>(1) << 54,
- static_cast<unsigned __int128>(1) << 57,
- static_cast<unsigned __int128>(1) << 60,
- static_cast<unsigned __int128>(1) << 64,
- static_cast<unsigned __int128>(1) << 67,
- static_cast<unsigned __int128>(1) << 70,
- static_cast<unsigned __int128>(1) << 74,
- static_cast<unsigned __int128>(1) << 77,
- static_cast<unsigned __int128>(1) << 80,
- static_cast<unsigned __int128>(1) << 84,
- static_cast<unsigned __int128>(1) << 87,
- static_cast<unsigned __int128>(1) << 90,
- static_cast<unsigned __int128>(1) << 94,
- static_cast<unsigned __int128>(1) << 97,
- static_cast<unsigned __int128>(1) << 100,
- static_cast<unsigned __int128>(1) << 103,
- static_cast<unsigned __int128>(1) << 107,
- static_cast<unsigned __int128>(1) << 110,
- static_cast<unsigned __int128>(1) << 113,
- static_cast<unsigned __int128>(1) << 117,
- static_cast<unsigned __int128>(1) << 120,
- static_cast<unsigned __int128>(1) << 123,
- static_cast<unsigned __int128>(1) << 127,
- };
- __int128 int128Pos[] = {
- 0,
- static_cast<__int128>(1) << 0,
- static_cast<__int128>(1) << 4,
- static_cast<__int128>(1) << 7,
- static_cast<__int128>(1) << 10,
- static_cast<__int128>(1) << 14,
- static_cast<__int128>(1) << 17,
- static_cast<__int128>(1) << 20,
- static_cast<__int128>(1) << 24,
- static_cast<__int128>(1) << 27,
- static_cast<__int128>(1) << 30,
- static_cast<__int128>(1) << 34,
- static_cast<__int128>(1) << 37,
- static_cast<__int128>(1) << 40,
- static_cast<__int128>(1) << 44,
- static_cast<__int128>(1) << 47,
- static_cast<__int128>(1) << 50,
- static_cast<__int128>(1) << 54,
- static_cast<__int128>(1) << 57,
- static_cast<__int128>(1) << 60,
- static_cast<__int128>(1) << 64,
- static_cast<__int128>(1) << 67,
- static_cast<__int128>(1) << 70,
- static_cast<__int128>(1) << 74,
- static_cast<__int128>(1) << 77,
- static_cast<__int128>(1) << 80,
- static_cast<__int128>(1) << 84,
- static_cast<__int128>(1) << 87,
- static_cast<__int128>(1) << 90,
- static_cast<__int128>(1) << 94,
- static_cast<__int128>(1) << 97,
- static_cast<__int128>(1) << 100,
- static_cast<__int128>(1) << 103,
- static_cast<__int128>(1) << 107,
- static_cast<__int128>(1) << 110,
- static_cast<__int128>(1) << 113,
- static_cast<__int128>(1) << 117,
- static_cast<__int128>(1) << 120,
- static_cast<__int128>(1) << 123,
- static_cast<__int128>(3) << 125,
- };
- __int128 int128Neg[] = {
- 0,
- -(static_cast<__int128>(1) << 0),
- -(static_cast<__int128>(1) << 4),
- -(static_cast<__int128>(1) << 7),
- -(static_cast<__int128>(1) << 10),
- -(static_cast<__int128>(1) << 14),
- -(static_cast<__int128>(1) << 17),
- -(static_cast<__int128>(1) << 20),
- -(static_cast<__int128>(1) << 24),
- -(static_cast<__int128>(1) << 27),
- -(static_cast<__int128>(1) << 30),
- -(static_cast<__int128>(1) << 34),
- -(static_cast<__int128>(1) << 37),
- -(static_cast<__int128>(1) << 40),
- -(static_cast<__int128>(1) << 44),
- -(static_cast<__int128>(1) << 47),
- -(static_cast<__int128>(1) << 50),
- -(static_cast<__int128>(1) << 54),
- -(static_cast<__int128>(1) << 57),
- -(static_cast<__int128>(1) << 60),
- -(static_cast<__int128>(1) << 64),
- -(static_cast<__int128>(1) << 67),
- -(static_cast<__int128>(1) << 70),
- -(static_cast<__int128>(1) << 74),
- -(static_cast<__int128>(1) << 77),
- -(static_cast<__int128>(1) << 80),
- -(static_cast<__int128>(1) << 84),
- -(static_cast<__int128>(1) << 87),
- -(static_cast<__int128>(1) << 90),
- -(static_cast<__int128>(1) << 94),
- -(static_cast<__int128>(1) << 97),
- -(static_cast<__int128>(1) << 100),
- -(static_cast<__int128>(1) << 103),
- -(static_cast<__int128>(1) << 107),
- -(static_cast<__int128>(1) << 110),
- -(static_cast<__int128>(1) << 113),
- -(static_cast<__int128>(1) << 117),
- -(static_cast<__int128>(1) << 120),
- -(static_cast<__int128>(1) << 123),
- -(static_cast<__int128>(3) << 125),
- };
- #endif
- } // namespace conv_bench_detail
- } // namespace folly
- using namespace folly::conv_bench_detail;
- namespace {
- template <typename T>
- void checkArrayIndex(const T& array, size_t index) {
- DCHECK_LT(index, sizeof(array) / sizeof(array[0]));
- }
- } // namespace
- ////////////////////////////////////////////////////////////////////////////////
- // Benchmarks for ASCII to int conversion
- ////////////////////////////////////////////////////////////////////////////////
- // @author: Rajat Goel (rajat)
- static int64_t handwrittenAtoi(const char* start, const char* end) {
- bool positive = true;
- int64_t retVal = 0;
- if (start == end) {
- throw std::runtime_error("empty string");
- }
- while (start < end && isspace(*start)) {
- ++start;
- }
- switch (*start) {
- case '-':
- positive = false;
- FOLLY_FALLTHROUGH;
- case '+':
- ++start;
- FOLLY_FALLTHROUGH;
- default:
- break;
- }
- while (start < end && *start >= '0' && *start <= '9') {
- auto const newRetVal = retVal * 10 + (*start++ - '0');
- if (newRetVal < retVal) {
- throw std::runtime_error("overflow");
- }
- retVal = newRetVal;
- }
- if (start != end) {
- throw std::runtime_error("extra chars at the end");
- }
- return positive ? retVal : -retVal;
- }
- static StringPiece pc1 = "1234567890123456789";
- void handwrittenAtoiMeasure(unsigned int n, unsigned int digits) {
- auto p = pc1.subpiece(pc1.size() - digits, digits);
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(handwrittenAtoi(p.begin(), p.end()));
- }
- }
- void follyAtoiMeasure(unsigned int n, unsigned int digits) {
- auto p = pc1.subpiece(pc1.size() - digits, digits);
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(folly::to<int64_t>(p.begin(), p.end()));
- }
- }
- void clibAtoiMeasure(unsigned int n, unsigned int digits) {
- auto p = pc1.subpiece(pc1.size() - digits, digits);
- assert(*p.end() == 0);
- FOR_EACH_RANGE (i, 0, n) { doNotOptimizeAway(atoll(p.begin())); }
- }
- void lexicalCastMeasure(unsigned int n, unsigned int digits) {
- auto p = pc1.subpiece(pc1.size() - digits, digits);
- assert(*p.end() == 0);
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(boost::lexical_cast<uint64_t>(p.begin()));
- }
- }
- // Benchmarks for unsigned to string conversion, raw
- unsigned u64ToAsciiTable(uint64_t value, char* dst) {
- static const char digits[201] =
- "00010203040506070809"
- "10111213141516171819"
- "20212223242526272829"
- "30313233343536373839"
- "40414243444546474849"
- "50515253545556575859"
- "60616263646566676869"
- "70717273747576777879"
- "80818283848586878889"
- "90919293949596979899";
- uint32_t const length = digits10(value);
- uint32_t next = length - 1;
- while (value >= 100) {
- auto const i = (value % 100) * 2;
- value /= 100;
- dst[next] = digits[i + 1];
- dst[next - 1] = digits[i];
- next -= 2;
- }
- // Handle last 1-2 digits
- if (value < 10) {
- dst[next] = '0' + uint32_t(value);
- } else {
- auto i = uint32_t(value) * 2;
- dst[next] = digits[i + 1];
- dst[next - 1] = digits[i];
- }
- return length;
- }
- void u64ToAsciiTableBM(unsigned int n, size_t index) {
- checkArrayIndex(uint64Num, index);
- char buf[20];
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(u64ToAsciiTable(uint64Num[index] + (i % 8), buf));
- }
- }
- unsigned u64ToAsciiClassic(uint64_t value, char* dst) {
- // Write backwards.
- char* next = (char*)dst;
- char* start = next;
- do {
- *next++ = '0' + (value % 10);
- value /= 10;
- } while (value != 0);
- unsigned length = next - start;
- // Reverse in-place.
- next--;
- while (next > start) {
- char swap = *next;
- *next = *start;
- *start = swap;
- next--;
- start++;
- }
- return length;
- }
- void u64ToAsciiClassicBM(unsigned int n, size_t index) {
- checkArrayIndex(uint64Num, index);
- char buf[20];
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(u64ToAsciiClassic(uint64Num[index] + (i % 8), buf));
- }
- }
- void u64ToAsciiFollyBM(unsigned int n, size_t index) {
- checkArrayIndex(uint64Num, index);
- char buf[20];
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(uint64ToBufferUnsafe(uint64Num[index] + (i % 8), buf));
- }
- }
- // Benchmark unsigned to string conversion
- void u64ToStringClibMeasure(unsigned int n, size_t index) {
- // FOLLY_RANGE_CHECK_TO_STRING expands to std::to_string, except on Android
- // where std::to_string is not supported
- checkArrayIndex(uint64Num, index);
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(
- FOLLY_RANGE_CHECK_TO_STRING(uint64Num[index] + (i % 8)).size());
- }
- }
- void u64ToStringFollyMeasure(unsigned int n, size_t index) {
- checkArrayIndex(uint64Num, index);
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(to<std::string>(uint64Num[index] + (i % 8)).size());
- }
- }
- // Signed
- void i64ToStringFollyMeasurePos(unsigned int n, size_t index) {
- checkArrayIndex(int64Pos, index);
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(to<std::string>(int64Pos[index] + (i % 8)).size());
- }
- }
- void i64ToStringFollyMeasureNeg(unsigned int n, size_t index) {
- checkArrayIndex(int64Neg, index);
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(to<std::string>(int64Neg[index] - (i % 8)).size());
- }
- }
- // Benchmark uitoa with string append
- void u2aAppendClassicBM(unsigned int n, size_t index) {
- checkArrayIndex(uint64Num, index);
- string s;
- FOR_EACH_RANGE (i, 0, n) {
- // auto buf = &s.back() + 1;
- char buffer[20];
- s.append(buffer, u64ToAsciiClassic(uint64Num[index] + (i % 8), buffer));
- doNotOptimizeAway(s.size());
- }
- }
- void u2aAppendFollyBM(unsigned int n, size_t index) {
- checkArrayIndex(uint64Num, index);
- string s;
- FOR_EACH_RANGE (i, 0, n) {
- // auto buf = &s.back() + 1;
- char buffer[20];
- s.append(buffer, uint64ToBufferUnsafe(uint64Num[index] + (i % 8), buffer));
- doNotOptimizeAway(s.size());
- }
- }
- template <class String>
- struct StringIdenticalToBM {
- StringIdenticalToBM() {}
- void operator()(unsigned int n, size_t len) const {
- String s;
- BENCHMARK_SUSPEND {
- s.append(len, '0');
- }
- FOR_EACH_RANGE (i, 0, n) {
- String result = to<String>(s);
- doNotOptimizeAway(result.size());
- }
- }
- };
- template <class String>
- struct StringVariadicToBM {
- StringVariadicToBM() {}
- void operator()(unsigned int n, size_t len) const {
- String s;
- BENCHMARK_SUSPEND {
- s.append(len, '0');
- }
- FOR_EACH_RANGE (i, 0, n) {
- String result = to<String>(s, nullptr);
- doNotOptimizeAway(result.size());
- }
- }
- };
- namespace folly {
- namespace conv_bench_detail {
- // Keep this data global and non-const, so the compiler cannot make
- // any assumptions about the actual values at compile time
- size_t bigInt = 11424545345345;
- size_t smallInt = 104;
- char someString[] = "this is some nice string";
- char otherString[] = "this is a long string, so it's not so nice";
- char reallyShort[] = "meh";
- std::string stdString = "std::strings are very nice";
- float fValue = 1.2355f;
- double dValue = 345345345.435;
- } // namespace conv_bench_detail
- } // namespace folly
- BENCHMARK(preallocateTestNoFloat, n) {
- for (size_t i = 0; i < n; ++i) {
- doNotOptimizeAway(
- to<std::string>(bigInt, someString, stdString, otherString).size());
- doNotOptimizeAway(to<std::string>(reallyShort, smallInt).size());
- doNotOptimizeAway(to<std::string>(bigInt, stdString).size());
- doNotOptimizeAway(
- to<std::string>(bigInt, stdString, dValue, otherString).size());
- doNotOptimizeAway(to<std::string>(bigInt, someString, reallyShort).size());
- }
- }
- BENCHMARK(preallocateTestFloat, n) {
- for (size_t i = 0; i < n; ++i) {
- doNotOptimizeAway(to<std::string>(stdString, ',', fValue, dValue).size());
- doNotOptimizeAway(to<std::string>(stdString, ',', dValue).size());
- }
- }
- namespace folly {
- namespace conv_bench_detail {
- // Keep this data global and non-const, so the compiler cannot make
- // any assumptions about the actual values at compile time
- int8_t i8s[] = {
- -(static_cast<int8_t>(1) << 4),
- static_cast<int8_t>(1) << 5,
- -(static_cast<int8_t>(1) << 6),
- };
- uint8_t u8s[] = {
- static_cast<uint8_t>(1) << 4,
- static_cast<uint8_t>(1) << 5,
- static_cast<uint8_t>(1) << 7,
- };
- int16_t i16s[] = {
- -(static_cast<int16_t>(1) << 8),
- static_cast<int16_t>(1) << 12,
- -(static_cast<int16_t>(1) << 14),
- };
- uint16_t u16s[] = {
- static_cast<uint16_t>(1) << 8,
- static_cast<uint16_t>(1) << 12,
- static_cast<uint16_t>(1) << 15,
- };
- int32_t i32s[] = {
- -(static_cast<int32_t>(1) << 16),
- static_cast<int32_t>(1) << 25,
- -(static_cast<int32_t>(1) << 30),
- };
- uint32_t u32s[] = {
- static_cast<uint32_t>(1) << 16,
- static_cast<uint32_t>(1) << 25,
- static_cast<uint32_t>(1) << 31,
- };
- int64_t i64s[] = {
- -(static_cast<int64_t>(1) << 32),
- static_cast<int64_t>(1) << 50,
- -(static_cast<int64_t>(1) << 62),
- };
- uint64_t u64s[] = {
- static_cast<uint64_t>(1) << 32,
- static_cast<uint64_t>(1) << 50,
- static_cast<uint64_t>(1) << 63,
- };
- } // namespace conv_bench_detail
- } // namespace folly
- BENCHMARK(preallocateTestInt8, n) {
- for (size_t i = 0; i < n; ++i) {
- doNotOptimizeAway(to<std::string>(
- i8s[0],
- ',',
- u8s[0],
- ',',
- i8s[1],
- ',',
- u8s[1],
- ',',
- i8s[2],
- ',',
- u8s[2])
- .size());
- }
- }
- BENCHMARK(preallocateTestInt16, n) {
- for (size_t i = 0; i < n; ++i) {
- doNotOptimizeAway(to<std::string>(
- i16s[0],
- ',',
- u16s[0],
- ',',
- i16s[1],
- ',',
- u16s[1],
- ',',
- i16s[2],
- ',',
- u16s[2])
- .size());
- }
- }
- BENCHMARK(preallocateTestInt32, n) {
- for (size_t i = 0; i < n; ++i) {
- doNotOptimizeAway(to<std::string>(
- i32s[0],
- ',',
- u32s[0],
- ',',
- i32s[1],
- ',',
- u32s[1],
- ',',
- i32s[2],
- ',',
- u32s[2])
- .size());
- }
- }
- BENCHMARK(preallocateTestInt64, n) {
- for (size_t i = 0; i < n; ++i) {
- doNotOptimizeAway(to<std::string>(
- i64s[0],
- ',',
- u64s[0],
- ',',
- i64s[1],
- ',',
- u64s[1],
- ',',
- i64s[2],
- ',',
- u64s[2])
- .size());
- }
- }
- #if FOLLY_HAVE_INT128_T
- namespace {
- __int128 i128s[] = {
- -(static_cast<__int128>(1) << 2),
- static_cast<__int128>(1) << 100,
- -(static_cast<__int128>(1) << 126),
- };
- unsigned __int128 u128s[] = {
- static_cast<unsigned __int128>(1) << 2,
- static_cast<unsigned __int128>(1) << 100,
- static_cast<unsigned __int128>(1) << 127,
- };
- } // namespace
- BENCHMARK(preallocateTestInt128, n) {
- for (size_t i = 0; i < n; ++i) {
- doNotOptimizeAway(to<std::string>(
- i128s[0],
- ',',
- u128s[0],
- ',',
- i128s[1],
- ',',
- u128s[1],
- ',',
- i128s[2],
- ',',
- u128s[2])
- .size());
- }
- }
- BENCHMARK(preallocateTestNoFloatWithInt128, n) {
- for (size_t i = 0; i < n; ++i) {
- doNotOptimizeAway(
- to<std::string>(bigInt, someString, stdString, otherString).size());
- doNotOptimizeAway(
- to<std::string>(reallyShort, u128s[0], smallInt, i128s[2]).size());
- doNotOptimizeAway(
- to<std::string>(bigInt, i128s[0], stdString, u128s[1]).size());
- doNotOptimizeAway(
- to<std::string>(bigInt, stdString, dValue, otherString).size());
- doNotOptimizeAway(
- to<std::string>(bigInt, u128s[2], someString, reallyShort).size());
- }
- }
- #endif
- BENCHMARK_DRAW_LINE();
- static const StringIdenticalToBM<std::string> stringIdenticalToBM;
- static const StringVariadicToBM<std::string> stringVariadicToBM;
- static const StringIdenticalToBM<fbstring> fbstringIdenticalToBM;
- static const StringVariadicToBM<fbstring> fbstringVariadicToBM;
- #define DEFINE_BENCHMARK_GROUP(n) \
- BENCHMARK_PARAM(u64ToAsciiClassicBM, n) \
- BENCHMARK_RELATIVE_PARAM(u64ToAsciiTableBM, n) \
- BENCHMARK_RELATIVE_PARAM(u64ToAsciiFollyBM, n) \
- BENCHMARK_DRAW_LINE()
- DEFINE_BENCHMARK_GROUP(1);
- DEFINE_BENCHMARK_GROUP(2);
- DEFINE_BENCHMARK_GROUP(3);
- DEFINE_BENCHMARK_GROUP(4);
- DEFINE_BENCHMARK_GROUP(5);
- DEFINE_BENCHMARK_GROUP(6);
- DEFINE_BENCHMARK_GROUP(7);
- DEFINE_BENCHMARK_GROUP(8);
- DEFINE_BENCHMARK_GROUP(9);
- DEFINE_BENCHMARK_GROUP(10);
- DEFINE_BENCHMARK_GROUP(11);
- DEFINE_BENCHMARK_GROUP(12);
- DEFINE_BENCHMARK_GROUP(13);
- DEFINE_BENCHMARK_GROUP(14);
- DEFINE_BENCHMARK_GROUP(15);
- DEFINE_BENCHMARK_GROUP(16);
- DEFINE_BENCHMARK_GROUP(17);
- DEFINE_BENCHMARK_GROUP(18);
- DEFINE_BENCHMARK_GROUP(19);
- DEFINE_BENCHMARK_GROUP(20);
- #undef DEFINE_BENCHMARK_GROUP
- #define DEFINE_BENCHMARK_GROUP(n) \
- BENCHMARK_PARAM(u64ToStringClibMeasure, n) \
- BENCHMARK_RELATIVE_PARAM(u64ToStringFollyMeasure, n) \
- BENCHMARK_RELATIVE_PARAM(i64ToStringFollyMeasurePos, n) \
- BENCHMARK_RELATIVE_PARAM(i64ToStringFollyMeasureNeg, n) \
- BENCHMARK_DRAW_LINE()
- DEFINE_BENCHMARK_GROUP(1);
- DEFINE_BENCHMARK_GROUP(2);
- DEFINE_BENCHMARK_GROUP(3);
- DEFINE_BENCHMARK_GROUP(4);
- DEFINE_BENCHMARK_GROUP(5);
- DEFINE_BENCHMARK_GROUP(6);
- DEFINE_BENCHMARK_GROUP(7);
- DEFINE_BENCHMARK_GROUP(8);
- DEFINE_BENCHMARK_GROUP(9);
- DEFINE_BENCHMARK_GROUP(10);
- DEFINE_BENCHMARK_GROUP(11);
- DEFINE_BENCHMARK_GROUP(12);
- DEFINE_BENCHMARK_GROUP(13);
- DEFINE_BENCHMARK_GROUP(14);
- DEFINE_BENCHMARK_GROUP(15);
- DEFINE_BENCHMARK_GROUP(16);
- DEFINE_BENCHMARK_GROUP(17);
- DEFINE_BENCHMARK_GROUP(18);
- DEFINE_BENCHMARK_GROUP(19);
- // Only for u64
- BENCHMARK_PARAM(u64ToStringClibMeasure, 20)
- BENCHMARK_RELATIVE_PARAM(u64ToStringFollyMeasure, 20)
- BENCHMARK_DRAW_LINE();
- #undef DEFINE_BENCHMARK_GROUP
- #if FOLLY_HAVE_INT128_T
- void u128ToStringFollyMeasure(unsigned int n, size_t index) {
- checkArrayIndex(uint128Num, index);
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(to<std::string>(uint128Num[index] + (i % 8)).size());
- }
- }
- void i128ToStringFollyMeasurePos(unsigned int n, size_t index) {
- checkArrayIndex(int128Pos, index);
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(to<std::string>(int128Pos[index] + (i % 8)).size());
- }
- }
- void i128ToStringFollyMeasureNeg(unsigned int n, size_t index) {
- checkArrayIndex(int128Neg, index);
- FOR_EACH_RANGE (i, 0, n) {
- doNotOptimizeAway(to<std::string>(int128Neg[index] + (i % 8)).size());
- }
- }
- #define DEFINE_BENCHMARK_GROUP(n) \
- BENCHMARK_PARAM(u128ToStringFollyMeasure, n) \
- BENCHMARK_RELATIVE_PARAM(i128ToStringFollyMeasurePos, n) \
- BENCHMARK_RELATIVE_PARAM(i128ToStringFollyMeasureNeg, n) \
- BENCHMARK_DRAW_LINE()
- DEFINE_BENCHMARK_GROUP(1);
- DEFINE_BENCHMARK_GROUP(2);
- DEFINE_BENCHMARK_GROUP(3);
- DEFINE_BENCHMARK_GROUP(4);
- DEFINE_BENCHMARK_GROUP(5);
- DEFINE_BENCHMARK_GROUP(6);
- DEFINE_BENCHMARK_GROUP(7);
- DEFINE_BENCHMARK_GROUP(8);
- DEFINE_BENCHMARK_GROUP(9);
- DEFINE_BENCHMARK_GROUP(10);
- DEFINE_BENCHMARK_GROUP(11);
- DEFINE_BENCHMARK_GROUP(12);
- DEFINE_BENCHMARK_GROUP(13);
- DEFINE_BENCHMARK_GROUP(14);
- DEFINE_BENCHMARK_GROUP(15);
- DEFINE_BENCHMARK_GROUP(16);
- DEFINE_BENCHMARK_GROUP(17);
- DEFINE_BENCHMARK_GROUP(18);
- DEFINE_BENCHMARK_GROUP(19);
- DEFINE_BENCHMARK_GROUP(20);
- DEFINE_BENCHMARK_GROUP(21);
- DEFINE_BENCHMARK_GROUP(22);
- DEFINE_BENCHMARK_GROUP(23);
- DEFINE_BENCHMARK_GROUP(24);
- DEFINE_BENCHMARK_GROUP(25);
- DEFINE_BENCHMARK_GROUP(26);
- DEFINE_BENCHMARK_GROUP(27);
- DEFINE_BENCHMARK_GROUP(28);
- DEFINE_BENCHMARK_GROUP(29);
- DEFINE_BENCHMARK_GROUP(30);
- DEFINE_BENCHMARK_GROUP(31);
- DEFINE_BENCHMARK_GROUP(32);
- DEFINE_BENCHMARK_GROUP(33);
- DEFINE_BENCHMARK_GROUP(34);
- DEFINE_BENCHMARK_GROUP(35);
- DEFINE_BENCHMARK_GROUP(36);
- DEFINE_BENCHMARK_GROUP(37);
- DEFINE_BENCHMARK_GROUP(38);
- DEFINE_BENCHMARK_GROUP(39);
- BENCHMARK_DRAW_LINE();
- #undef DEFINE_BENCHMARK_GROUP
- #endif
- #define DEFINE_BENCHMARK_GROUP(n) \
- BENCHMARK_PARAM(clibAtoiMeasure, n) \
- BENCHMARK_RELATIVE_PARAM(lexicalCastMeasure, n) \
- BENCHMARK_RELATIVE_PARAM(handwrittenAtoiMeasure, n) \
- BENCHMARK_RELATIVE_PARAM(follyAtoiMeasure, n) \
- BENCHMARK_DRAW_LINE()
- DEFINE_BENCHMARK_GROUP(1);
- DEFINE_BENCHMARK_GROUP(2);
- DEFINE_BENCHMARK_GROUP(3);
- DEFINE_BENCHMARK_GROUP(4);
- DEFINE_BENCHMARK_GROUP(5);
- DEFINE_BENCHMARK_GROUP(6);
- DEFINE_BENCHMARK_GROUP(7);
- DEFINE_BENCHMARK_GROUP(8);
- DEFINE_BENCHMARK_GROUP(9);
- DEFINE_BENCHMARK_GROUP(10);
- DEFINE_BENCHMARK_GROUP(11);
- DEFINE_BENCHMARK_GROUP(12);
- DEFINE_BENCHMARK_GROUP(13);
- DEFINE_BENCHMARK_GROUP(14);
- DEFINE_BENCHMARK_GROUP(15);
- DEFINE_BENCHMARK_GROUP(16);
- DEFINE_BENCHMARK_GROUP(17);
- DEFINE_BENCHMARK_GROUP(18);
- DEFINE_BENCHMARK_GROUP(19);
- #undef DEFINE_BENCHMARK_GROUP
- #define DEFINE_BENCHMARK_GROUP(T, n) \
- BENCHMARK_PARAM(T##VariadicToBM, n) \
- BENCHMARK_RELATIVE_PARAM(T##IdenticalToBM, n) \
- BENCHMARK_DRAW_LINE()
- DEFINE_BENCHMARK_GROUP(string, 32);
- DEFINE_BENCHMARK_GROUP(string, 1024);
- DEFINE_BENCHMARK_GROUP(string, 32768);
- DEFINE_BENCHMARK_GROUP(fbstring, 32);
- DEFINE_BENCHMARK_GROUP(fbstring, 1024);
- DEFINE_BENCHMARK_GROUP(fbstring, 32768);
- #undef DEFINE_BENCHMARK_GROUP
- namespace {
- template <typename T>
- inline void stringToTypeClassic(const char* str, uint32_t n) {
- for (uint32_t i = 0; i < n; ++i) {
- try {
- auto val = to<T>(str);
- doNotOptimizeAway(val);
- } catch (const std::exception& e) {
- doNotOptimizeAway(e.what());
- }
- doNotOptimizeAway(i);
- }
- }
- template <typename T>
- inline void stringToTypeOptional(const char* str, uint32_t n) {
- for (uint32_t i = 0; i < n; ++i) {
- auto val = tryTo<T>(str);
- if (val.hasValue()) {
- doNotOptimizeAway(val.value());
- }
- }
- }
- template <typename T>
- inline void ptrPairToIntClassic(StringPiece sp, uint32_t n) {
- for (uint32_t i = 0; i < n; ++i) {
- try {
- auto val = to<T>(sp.begin(), sp.end());
- doNotOptimizeAway(val);
- } catch (const std::exception& e) {
- doNotOptimizeAway(e.what());
- }
- doNotOptimizeAway(i);
- }
- }
- template <typename T>
- inline void ptrPairToIntOptional(StringPiece sp, uint32_t n) {
- for (uint32_t i = 0; i < n; ++i) {
- auto val = tryTo<T>(sp.begin(), sp.end());
- if (val.hasValue()) {
- doNotOptimizeAway(val.value());
- }
- }
- }
- constexpr uint32_t kArithNumIter = 10000;
- template <typename T, typename U>
- inline size_t arithToArithClassic(const U* in, uint32_t numItems) {
- for (uint32_t i = 0; i < kArithNumIter; ++i) {
- for (uint32_t j = 0; j < numItems; ++j) {
- try {
- auto val = to<T>(in[j]);
- doNotOptimizeAway(val);
- } catch (const std::exception& e) {
- doNotOptimizeAway(e.what());
- }
- doNotOptimizeAway(j);
- }
- doNotOptimizeAway(i);
- }
- return kArithNumIter * numItems;
- }
- template <typename T, typename U>
- inline size_t arithToArithOptional(const U* in, uint32_t numItems) {
- for (uint32_t i = 0; i < kArithNumIter; ++i) {
- for (uint32_t j = 0; j < numItems; ++j) {
- auto val = tryTo<T>(*in);
- doNotOptimizeAway(val.hasValue());
- if (val.hasValue()) {
- auto v2 = val.value();
- doNotOptimizeAway(v2);
- }
- doNotOptimizeAway(j);
- }
- doNotOptimizeAway(i);
- }
- return kArithNumIter * numItems;
- }
- } // namespace
- namespace folly {
- namespace conv_bench_detail {
- // Keep this data global and non-const, so the compiler cannot make
- // any assumptions about the actual values at compile time
- std::array<int, 4> int2ScharGood{{-128, 127, 0, -50}};
- std::array<int, 4> int2ScharBad{{-129, 128, 255, 10000}};
- std::array<int, 4> int2UcharGood{{0, 1, 254, 255}};
- std::array<int, 4> int2UcharBad{{-128, -1000, 256, -1}};
- std::array<long long, 4> ll2SintOrFloatGood{{-2, -1, 0, 1}};
- std::array<long long, 4> ll2SintOrFloatBad{{
- std::numeric_limits<long long>::min() / 5,
- std::numeric_limits<long long>::min() / 2,
- std::numeric_limits<long long>::max() / 2,
- std::numeric_limits<long long>::max() / 5,
- }};
- std::array<long long, 4> ll2UintGood{{1, 2, 3, 4}};
- std::array<long long, 4> ll2UintBad{{-1, -2, -3, -4}};
- std::array<double, 4> double2FloatGood{{1.0, 1.25, 2.5, 1000.0}};
- std::array<double, 4> double2FloatBad{{1e100, 1e101, 1e102, 1e103}};
- std::array<double, 4> double2IntGood{{1.0, 10.0, 100.0, 1000.0}};
- std::array<double, 4> double2IntBad{{1e100, 1.25, 2.5, 100.00001}};
- } // namespace conv_bench_detail
- } // namespace folly
- #define STRING_TO_TYPE_BENCHMARK(type, name, pass, fail) \
- BENCHMARK(stringTo##name##Classic, n) { \
- stringToTypeClassic<type>(pass, n); \
- } \
- BENCHMARK(stringTo##name##ClassicError, n) { \
- stringToTypeClassic<type>(fail, n); \
- } \
- BENCHMARK(stringTo##name##Optional, n) { \
- stringToTypeOptional<type>(pass, n); \
- } \
- BENCHMARK(stringTo##name##OptionalError, n) { \
- stringToTypeOptional<type>(fail, n); \
- }
- #define PTR_PAIR_TO_INT_BENCHMARK(type, name, pass, fail) \
- BENCHMARK(ptrPairTo##name##Classic, n) { \
- ptrPairToIntClassic<type>(pass, n); \
- } \
- BENCHMARK(ptrPairTo##name##ClassicError, n) { \
- ptrPairToIntClassic<type>(fail, n); \
- } \
- BENCHMARK(ptrPairTo##name##Optional, n) { \
- ptrPairToIntOptional<type>(pass, n); \
- } \
- BENCHMARK(ptrPairTo##name##OptionalError, n) { \
- ptrPairToIntOptional<type>(fail, n); \
- }
- #define ARITH_TO_ARITH_BENCHMARK(type, name, pass, fail) \
- BENCHMARK_MULTI(name##Classic) { \
- return arithToArithClassic<type>(pass.data(), pass.size()); \
- } \
- BENCHMARK_MULTI(name##ClassicError) { \
- return arithToArithClassic<type>(fail.data(), fail.size()); \
- } \
- BENCHMARK_MULTI(name##Optional) { \
- return arithToArithOptional<type>(pass.data(), pass.size()); \
- } \
- BENCHMARK_MULTI(name##OptionalError) { \
- return arithToArithOptional<type>(fail.data(), fail.size()); \
- }
- #define INT_TO_ARITH_BENCHMARK(type, name, pass, fail) \
- ARITH_TO_ARITH_BENCHMARK(type, intTo##name, pass, fail)
- #define FLOAT_TO_ARITH_BENCHMARK(type, name, pass, fail) \
- ARITH_TO_ARITH_BENCHMARK(type, floatTo##name, pass, fail)
- STRING_TO_TYPE_BENCHMARK(bool, BoolNum, " 1 ", "2")
- STRING_TO_TYPE_BENCHMARK(bool, BoolStr, "true", "xxxx")
- BENCHMARK_DRAW_LINE();
- STRING_TO_TYPE_BENCHMARK(float, FloatNum, " 3.14 ", "3e5000x")
- STRING_TO_TYPE_BENCHMARK(float, FloatStr, "-infinity", "xxxx")
- STRING_TO_TYPE_BENCHMARK(double, DoubleNum, " 3.14 ", "3e5000x")
- STRING_TO_TYPE_BENCHMARK(double, DoubleStr, "-infinity", "xxxx")
- BENCHMARK_DRAW_LINE();
- STRING_TO_TYPE_BENCHMARK(signed char, CharSigned, " -47 ", "1000")
- STRING_TO_TYPE_BENCHMARK(unsigned char, CharUnsigned, " 47 ", "-47")
- STRING_TO_TYPE_BENCHMARK(int, IntSigned, " -4711 ", "-10000000000000000000000")
- STRING_TO_TYPE_BENCHMARK(unsigned int, IntUnsigned, " 4711 ", "-4711")
- STRING_TO_TYPE_BENCHMARK(
- long long,
- LongLongSigned,
- " -8123456789123456789 ",
- "-10000000000000000000000")
- STRING_TO_TYPE_BENCHMARK(
- unsigned long long,
- LongLongUnsigned,
- " 18123456789123456789 ",
- "-4711")
- BENCHMARK_DRAW_LINE();
- PTR_PAIR_TO_INT_BENCHMARK(signed char, CharSigned, "-47", "1000")
- PTR_PAIR_TO_INT_BENCHMARK(unsigned char, CharUnsigned, "47", "1000")
- PTR_PAIR_TO_INT_BENCHMARK(int, IntSigned, "-4711", "-10000000000000000000000")
- PTR_PAIR_TO_INT_BENCHMARK(
- unsigned int,
- IntUnsigned,
- "4711",
- "10000000000000000000000")
- PTR_PAIR_TO_INT_BENCHMARK(
- long long,
- LongLongSigned,
- "-8123456789123456789",
- "-10000000000000000000000")
- PTR_PAIR_TO_INT_BENCHMARK(
- unsigned long long,
- LongLongUnsigned,
- "18123456789123456789",
- "20000000000000000000")
- BENCHMARK_DRAW_LINE();
- INT_TO_ARITH_BENCHMARK(signed char, CharSigned, int2ScharGood, int2ScharBad)
- INT_TO_ARITH_BENCHMARK(unsigned char, CharUnsigned, int2UcharGood, int2UcharBad)
- INT_TO_ARITH_BENCHMARK(int, IntSigned, ll2SintOrFloatGood, ll2SintOrFloatBad)
- INT_TO_ARITH_BENCHMARK(unsigned int, IntUnsigned, ll2UintGood, ll2UintBad)
- BENCHMARK_DRAW_LINE();
- INT_TO_ARITH_BENCHMARK(float, Float, ll2SintOrFloatGood, ll2SintOrFloatBad)
- BENCHMARK_DRAW_LINE();
- FLOAT_TO_ARITH_BENCHMARK(float, Float, double2FloatGood, double2FloatBad)
- BENCHMARK_DRAW_LINE();
- FLOAT_TO_ARITH_BENCHMARK(int, Int, double2IntGood, double2IntBad)
- #undef STRING_TO_TYPE_BENCHMARK
- #undef PTR_PAIR_TO_INT_BENCHMARK
- #undef ARITH_TO_ARITH_BENCHMARK
- #undef INT_TO_ARITH_BENCHMARK
- #undef FLOAT_TO_ARITH_BENCHMARK
- int main(int argc, char** argv) {
- gflags::ParseCommandLineFlags(&argc, &argv, true);
- folly::runBenchmarks();
- return 0;
- }
|