ConvBenchmark.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  1. /*
  2. * Copyright 2016-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. #include <folly/Conv.h>
  17. #include <boost/lexical_cast.hpp>
  18. #include <folly/Benchmark.h>
  19. #include <folly/CppAttributes.h>
  20. #include <folly/container/Foreach.h>
  21. #include <array>
  22. #include <limits>
  23. #include <stdexcept>
  24. using namespace std;
  25. using namespace folly;
  26. // Android doesn't support std::to_string so just use a placeholder there.
  27. #ifdef __ANDROID__
  28. #define FOLLY_RANGE_CHECK_TO_STRING(x) std::string("N/A")
  29. #else
  30. #define FOLLY_RANGE_CHECK_TO_STRING(x) std::to_string(x)
  31. #endif
  32. namespace folly {
  33. namespace conv_bench_detail {
  34. // Keep this data global and non-const, so the compiler cannot make
  35. // any assumptions about the actual values at compile time
  36. uint64_t uint64Num[] = {
  37. 0,
  38. 1ULL,
  39. 12ULL,
  40. 123ULL,
  41. 1234ULL,
  42. 12345ULL,
  43. 123456ULL,
  44. 1234567ULL,
  45. 12345678ULL,
  46. 123456789ULL,
  47. 1234567890ULL,
  48. 12345678901ULL,
  49. 123456789012ULL,
  50. 1234567890123ULL,
  51. 12345678901234ULL,
  52. 123456789012345ULL,
  53. 1234567890123456ULL,
  54. 12345678901234567ULL,
  55. 123456789012345678ULL,
  56. 1234567890123456789ULL,
  57. 12345678901234567890ULL,
  58. };
  59. int64_t int64Pos[] = {
  60. 0,
  61. 1LL,
  62. 12LL,
  63. 123LL,
  64. 1234LL,
  65. 12345LL,
  66. 123456LL,
  67. 1234567LL,
  68. 12345678LL,
  69. 123456789LL,
  70. 1234567890LL,
  71. 12345678901LL,
  72. 123456789012LL,
  73. 1234567890123LL,
  74. 12345678901234LL,
  75. 123456789012345LL,
  76. 1234567890123456LL,
  77. 12345678901234567LL,
  78. 123456789012345678LL,
  79. 1234567890123456789LL,
  80. };
  81. int64_t int64Neg[] = {
  82. 0,
  83. -1LL,
  84. -12LL,
  85. -123LL,
  86. -1234LL,
  87. -12345LL,
  88. -123456LL,
  89. -1234567LL,
  90. -12345678LL,
  91. -123456789LL,
  92. -1234567890LL,
  93. -12345678901LL,
  94. -123456789012LL,
  95. -1234567890123LL,
  96. -12345678901234LL,
  97. -123456789012345LL,
  98. -1234567890123456LL,
  99. -12345678901234567LL,
  100. -123456789012345678LL,
  101. -1234567890123456789LL,
  102. };
  103. #if FOLLY_HAVE_INT128_T
  104. unsigned __int128 uint128Num[] = {
  105. 0,
  106. static_cast<unsigned __int128>(1) << 0,
  107. static_cast<unsigned __int128>(1) << 4,
  108. static_cast<unsigned __int128>(1) << 7,
  109. static_cast<unsigned __int128>(1) << 10,
  110. static_cast<unsigned __int128>(1) << 14,
  111. static_cast<unsigned __int128>(1) << 17,
  112. static_cast<unsigned __int128>(1) << 20,
  113. static_cast<unsigned __int128>(1) << 24,
  114. static_cast<unsigned __int128>(1) << 27,
  115. static_cast<unsigned __int128>(1) << 30,
  116. static_cast<unsigned __int128>(1) << 34,
  117. static_cast<unsigned __int128>(1) << 37,
  118. static_cast<unsigned __int128>(1) << 40,
  119. static_cast<unsigned __int128>(1) << 44,
  120. static_cast<unsigned __int128>(1) << 47,
  121. static_cast<unsigned __int128>(1) << 50,
  122. static_cast<unsigned __int128>(1) << 54,
  123. static_cast<unsigned __int128>(1) << 57,
  124. static_cast<unsigned __int128>(1) << 60,
  125. static_cast<unsigned __int128>(1) << 64,
  126. static_cast<unsigned __int128>(1) << 67,
  127. static_cast<unsigned __int128>(1) << 70,
  128. static_cast<unsigned __int128>(1) << 74,
  129. static_cast<unsigned __int128>(1) << 77,
  130. static_cast<unsigned __int128>(1) << 80,
  131. static_cast<unsigned __int128>(1) << 84,
  132. static_cast<unsigned __int128>(1) << 87,
  133. static_cast<unsigned __int128>(1) << 90,
  134. static_cast<unsigned __int128>(1) << 94,
  135. static_cast<unsigned __int128>(1) << 97,
  136. static_cast<unsigned __int128>(1) << 100,
  137. static_cast<unsigned __int128>(1) << 103,
  138. static_cast<unsigned __int128>(1) << 107,
  139. static_cast<unsigned __int128>(1) << 110,
  140. static_cast<unsigned __int128>(1) << 113,
  141. static_cast<unsigned __int128>(1) << 117,
  142. static_cast<unsigned __int128>(1) << 120,
  143. static_cast<unsigned __int128>(1) << 123,
  144. static_cast<unsigned __int128>(1) << 127,
  145. };
  146. __int128 int128Pos[] = {
  147. 0,
  148. static_cast<__int128>(1) << 0,
  149. static_cast<__int128>(1) << 4,
  150. static_cast<__int128>(1) << 7,
  151. static_cast<__int128>(1) << 10,
  152. static_cast<__int128>(1) << 14,
  153. static_cast<__int128>(1) << 17,
  154. static_cast<__int128>(1) << 20,
  155. static_cast<__int128>(1) << 24,
  156. static_cast<__int128>(1) << 27,
  157. static_cast<__int128>(1) << 30,
  158. static_cast<__int128>(1) << 34,
  159. static_cast<__int128>(1) << 37,
  160. static_cast<__int128>(1) << 40,
  161. static_cast<__int128>(1) << 44,
  162. static_cast<__int128>(1) << 47,
  163. static_cast<__int128>(1) << 50,
  164. static_cast<__int128>(1) << 54,
  165. static_cast<__int128>(1) << 57,
  166. static_cast<__int128>(1) << 60,
  167. static_cast<__int128>(1) << 64,
  168. static_cast<__int128>(1) << 67,
  169. static_cast<__int128>(1) << 70,
  170. static_cast<__int128>(1) << 74,
  171. static_cast<__int128>(1) << 77,
  172. static_cast<__int128>(1) << 80,
  173. static_cast<__int128>(1) << 84,
  174. static_cast<__int128>(1) << 87,
  175. static_cast<__int128>(1) << 90,
  176. static_cast<__int128>(1) << 94,
  177. static_cast<__int128>(1) << 97,
  178. static_cast<__int128>(1) << 100,
  179. static_cast<__int128>(1) << 103,
  180. static_cast<__int128>(1) << 107,
  181. static_cast<__int128>(1) << 110,
  182. static_cast<__int128>(1) << 113,
  183. static_cast<__int128>(1) << 117,
  184. static_cast<__int128>(1) << 120,
  185. static_cast<__int128>(1) << 123,
  186. static_cast<__int128>(3) << 125,
  187. };
  188. __int128 int128Neg[] = {
  189. 0,
  190. -(static_cast<__int128>(1) << 0),
  191. -(static_cast<__int128>(1) << 4),
  192. -(static_cast<__int128>(1) << 7),
  193. -(static_cast<__int128>(1) << 10),
  194. -(static_cast<__int128>(1) << 14),
  195. -(static_cast<__int128>(1) << 17),
  196. -(static_cast<__int128>(1) << 20),
  197. -(static_cast<__int128>(1) << 24),
  198. -(static_cast<__int128>(1) << 27),
  199. -(static_cast<__int128>(1) << 30),
  200. -(static_cast<__int128>(1) << 34),
  201. -(static_cast<__int128>(1) << 37),
  202. -(static_cast<__int128>(1) << 40),
  203. -(static_cast<__int128>(1) << 44),
  204. -(static_cast<__int128>(1) << 47),
  205. -(static_cast<__int128>(1) << 50),
  206. -(static_cast<__int128>(1) << 54),
  207. -(static_cast<__int128>(1) << 57),
  208. -(static_cast<__int128>(1) << 60),
  209. -(static_cast<__int128>(1) << 64),
  210. -(static_cast<__int128>(1) << 67),
  211. -(static_cast<__int128>(1) << 70),
  212. -(static_cast<__int128>(1) << 74),
  213. -(static_cast<__int128>(1) << 77),
  214. -(static_cast<__int128>(1) << 80),
  215. -(static_cast<__int128>(1) << 84),
  216. -(static_cast<__int128>(1) << 87),
  217. -(static_cast<__int128>(1) << 90),
  218. -(static_cast<__int128>(1) << 94),
  219. -(static_cast<__int128>(1) << 97),
  220. -(static_cast<__int128>(1) << 100),
  221. -(static_cast<__int128>(1) << 103),
  222. -(static_cast<__int128>(1) << 107),
  223. -(static_cast<__int128>(1) << 110),
  224. -(static_cast<__int128>(1) << 113),
  225. -(static_cast<__int128>(1) << 117),
  226. -(static_cast<__int128>(1) << 120),
  227. -(static_cast<__int128>(1) << 123),
  228. -(static_cast<__int128>(3) << 125),
  229. };
  230. #endif
  231. } // namespace conv_bench_detail
  232. } // namespace folly
  233. using namespace folly::conv_bench_detail;
  234. namespace {
  235. template <typename T>
  236. void checkArrayIndex(const T& array, size_t index) {
  237. DCHECK_LT(index, sizeof(array) / sizeof(array[0]));
  238. }
  239. } // namespace
  240. ////////////////////////////////////////////////////////////////////////////////
  241. // Benchmarks for ASCII to int conversion
  242. ////////////////////////////////////////////////////////////////////////////////
  243. // @author: Rajat Goel (rajat)
  244. static int64_t handwrittenAtoi(const char* start, const char* end) {
  245. bool positive = true;
  246. int64_t retVal = 0;
  247. if (start == end) {
  248. throw std::runtime_error("empty string");
  249. }
  250. while (start < end && isspace(*start)) {
  251. ++start;
  252. }
  253. switch (*start) {
  254. case '-':
  255. positive = false;
  256. FOLLY_FALLTHROUGH;
  257. case '+':
  258. ++start;
  259. FOLLY_FALLTHROUGH;
  260. default:
  261. break;
  262. }
  263. while (start < end && *start >= '0' && *start <= '9') {
  264. auto const newRetVal = retVal * 10 + (*start++ - '0');
  265. if (newRetVal < retVal) {
  266. throw std::runtime_error("overflow");
  267. }
  268. retVal = newRetVal;
  269. }
  270. if (start != end) {
  271. throw std::runtime_error("extra chars at the end");
  272. }
  273. return positive ? retVal : -retVal;
  274. }
  275. static StringPiece pc1 = "1234567890123456789";
  276. void handwrittenAtoiMeasure(unsigned int n, unsigned int digits) {
  277. auto p = pc1.subpiece(pc1.size() - digits, digits);
  278. FOR_EACH_RANGE (i, 0, n) {
  279. doNotOptimizeAway(handwrittenAtoi(p.begin(), p.end()));
  280. }
  281. }
  282. void follyAtoiMeasure(unsigned int n, unsigned int digits) {
  283. auto p = pc1.subpiece(pc1.size() - digits, digits);
  284. FOR_EACH_RANGE (i, 0, n) {
  285. doNotOptimizeAway(folly::to<int64_t>(p.begin(), p.end()));
  286. }
  287. }
  288. void clibAtoiMeasure(unsigned int n, unsigned int digits) {
  289. auto p = pc1.subpiece(pc1.size() - digits, digits);
  290. assert(*p.end() == 0);
  291. FOR_EACH_RANGE (i, 0, n) { doNotOptimizeAway(atoll(p.begin())); }
  292. }
  293. void lexicalCastMeasure(unsigned int n, unsigned int digits) {
  294. auto p = pc1.subpiece(pc1.size() - digits, digits);
  295. assert(*p.end() == 0);
  296. FOR_EACH_RANGE (i, 0, n) {
  297. doNotOptimizeAway(boost::lexical_cast<uint64_t>(p.begin()));
  298. }
  299. }
  300. // Benchmarks for unsigned to string conversion, raw
  301. unsigned u64ToAsciiTable(uint64_t value, char* dst) {
  302. static const char digits[201] =
  303. "00010203040506070809"
  304. "10111213141516171819"
  305. "20212223242526272829"
  306. "30313233343536373839"
  307. "40414243444546474849"
  308. "50515253545556575859"
  309. "60616263646566676869"
  310. "70717273747576777879"
  311. "80818283848586878889"
  312. "90919293949596979899";
  313. uint32_t const length = digits10(value);
  314. uint32_t next = length - 1;
  315. while (value >= 100) {
  316. auto const i = (value % 100) * 2;
  317. value /= 100;
  318. dst[next] = digits[i + 1];
  319. dst[next - 1] = digits[i];
  320. next -= 2;
  321. }
  322. // Handle last 1-2 digits
  323. if (value < 10) {
  324. dst[next] = '0' + uint32_t(value);
  325. } else {
  326. auto i = uint32_t(value) * 2;
  327. dst[next] = digits[i + 1];
  328. dst[next - 1] = digits[i];
  329. }
  330. return length;
  331. }
  332. void u64ToAsciiTableBM(unsigned int n, size_t index) {
  333. checkArrayIndex(uint64Num, index);
  334. char buf[20];
  335. FOR_EACH_RANGE (i, 0, n) {
  336. doNotOptimizeAway(u64ToAsciiTable(uint64Num[index] + (i % 8), buf));
  337. }
  338. }
  339. unsigned u64ToAsciiClassic(uint64_t value, char* dst) {
  340. // Write backwards.
  341. char* next = (char*)dst;
  342. char* start = next;
  343. do {
  344. *next++ = '0' + (value % 10);
  345. value /= 10;
  346. } while (value != 0);
  347. unsigned length = next - start;
  348. // Reverse in-place.
  349. next--;
  350. while (next > start) {
  351. char swap = *next;
  352. *next = *start;
  353. *start = swap;
  354. next--;
  355. start++;
  356. }
  357. return length;
  358. }
  359. void u64ToAsciiClassicBM(unsigned int n, size_t index) {
  360. checkArrayIndex(uint64Num, index);
  361. char buf[20];
  362. FOR_EACH_RANGE (i, 0, n) {
  363. doNotOptimizeAway(u64ToAsciiClassic(uint64Num[index] + (i % 8), buf));
  364. }
  365. }
  366. void u64ToAsciiFollyBM(unsigned int n, size_t index) {
  367. checkArrayIndex(uint64Num, index);
  368. char buf[20];
  369. FOR_EACH_RANGE (i, 0, n) {
  370. doNotOptimizeAway(uint64ToBufferUnsafe(uint64Num[index] + (i % 8), buf));
  371. }
  372. }
  373. // Benchmark unsigned to string conversion
  374. void u64ToStringClibMeasure(unsigned int n, size_t index) {
  375. // FOLLY_RANGE_CHECK_TO_STRING expands to std::to_string, except on Android
  376. // where std::to_string is not supported
  377. checkArrayIndex(uint64Num, index);
  378. FOR_EACH_RANGE (i, 0, n) {
  379. doNotOptimizeAway(
  380. FOLLY_RANGE_CHECK_TO_STRING(uint64Num[index] + (i % 8)).size());
  381. }
  382. }
  383. void u64ToStringFollyMeasure(unsigned int n, size_t index) {
  384. checkArrayIndex(uint64Num, index);
  385. FOR_EACH_RANGE (i, 0, n) {
  386. doNotOptimizeAway(to<std::string>(uint64Num[index] + (i % 8)).size());
  387. }
  388. }
  389. // Signed
  390. void i64ToStringFollyMeasurePos(unsigned int n, size_t index) {
  391. checkArrayIndex(int64Pos, index);
  392. FOR_EACH_RANGE (i, 0, n) {
  393. doNotOptimizeAway(to<std::string>(int64Pos[index] + (i % 8)).size());
  394. }
  395. }
  396. void i64ToStringFollyMeasureNeg(unsigned int n, size_t index) {
  397. checkArrayIndex(int64Neg, index);
  398. FOR_EACH_RANGE (i, 0, n) {
  399. doNotOptimizeAway(to<std::string>(int64Neg[index] - (i % 8)).size());
  400. }
  401. }
  402. // Benchmark uitoa with string append
  403. void u2aAppendClassicBM(unsigned int n, size_t index) {
  404. checkArrayIndex(uint64Num, index);
  405. string s;
  406. FOR_EACH_RANGE (i, 0, n) {
  407. // auto buf = &s.back() + 1;
  408. char buffer[20];
  409. s.append(buffer, u64ToAsciiClassic(uint64Num[index] + (i % 8), buffer));
  410. doNotOptimizeAway(s.size());
  411. }
  412. }
  413. void u2aAppendFollyBM(unsigned int n, size_t index) {
  414. checkArrayIndex(uint64Num, index);
  415. string s;
  416. FOR_EACH_RANGE (i, 0, n) {
  417. // auto buf = &s.back() + 1;
  418. char buffer[20];
  419. s.append(buffer, uint64ToBufferUnsafe(uint64Num[index] + (i % 8), buffer));
  420. doNotOptimizeAway(s.size());
  421. }
  422. }
  423. template <class String>
  424. struct StringIdenticalToBM {
  425. StringIdenticalToBM() {}
  426. void operator()(unsigned int n, size_t len) const {
  427. String s;
  428. BENCHMARK_SUSPEND {
  429. s.append(len, '0');
  430. }
  431. FOR_EACH_RANGE (i, 0, n) {
  432. String result = to<String>(s);
  433. doNotOptimizeAway(result.size());
  434. }
  435. }
  436. };
  437. template <class String>
  438. struct StringVariadicToBM {
  439. StringVariadicToBM() {}
  440. void operator()(unsigned int n, size_t len) const {
  441. String s;
  442. BENCHMARK_SUSPEND {
  443. s.append(len, '0');
  444. }
  445. FOR_EACH_RANGE (i, 0, n) {
  446. String result = to<String>(s, nullptr);
  447. doNotOptimizeAway(result.size());
  448. }
  449. }
  450. };
  451. namespace folly {
  452. namespace conv_bench_detail {
  453. // Keep this data global and non-const, so the compiler cannot make
  454. // any assumptions about the actual values at compile time
  455. size_t bigInt = 11424545345345;
  456. size_t smallInt = 104;
  457. char someString[] = "this is some nice string";
  458. char otherString[] = "this is a long string, so it's not so nice";
  459. char reallyShort[] = "meh";
  460. std::string stdString = "std::strings are very nice";
  461. float fValue = 1.2355f;
  462. double dValue = 345345345.435;
  463. } // namespace conv_bench_detail
  464. } // namespace folly
  465. BENCHMARK(preallocateTestNoFloat, n) {
  466. for (size_t i = 0; i < n; ++i) {
  467. doNotOptimizeAway(
  468. to<std::string>(bigInt, someString, stdString, otherString).size());
  469. doNotOptimizeAway(to<std::string>(reallyShort, smallInt).size());
  470. doNotOptimizeAway(to<std::string>(bigInt, stdString).size());
  471. doNotOptimizeAway(
  472. to<std::string>(bigInt, stdString, dValue, otherString).size());
  473. doNotOptimizeAway(to<std::string>(bigInt, someString, reallyShort).size());
  474. }
  475. }
  476. BENCHMARK(preallocateTestFloat, n) {
  477. for (size_t i = 0; i < n; ++i) {
  478. doNotOptimizeAway(to<std::string>(stdString, ',', fValue, dValue).size());
  479. doNotOptimizeAway(to<std::string>(stdString, ',', dValue).size());
  480. }
  481. }
  482. namespace folly {
  483. namespace conv_bench_detail {
  484. // Keep this data global and non-const, so the compiler cannot make
  485. // any assumptions about the actual values at compile time
  486. int8_t i8s[] = {
  487. -(static_cast<int8_t>(1) << 4),
  488. static_cast<int8_t>(1) << 5,
  489. -(static_cast<int8_t>(1) << 6),
  490. };
  491. uint8_t u8s[] = {
  492. static_cast<uint8_t>(1) << 4,
  493. static_cast<uint8_t>(1) << 5,
  494. static_cast<uint8_t>(1) << 7,
  495. };
  496. int16_t i16s[] = {
  497. -(static_cast<int16_t>(1) << 8),
  498. static_cast<int16_t>(1) << 12,
  499. -(static_cast<int16_t>(1) << 14),
  500. };
  501. uint16_t u16s[] = {
  502. static_cast<uint16_t>(1) << 8,
  503. static_cast<uint16_t>(1) << 12,
  504. static_cast<uint16_t>(1) << 15,
  505. };
  506. int32_t i32s[] = {
  507. -(static_cast<int32_t>(1) << 16),
  508. static_cast<int32_t>(1) << 25,
  509. -(static_cast<int32_t>(1) << 30),
  510. };
  511. uint32_t u32s[] = {
  512. static_cast<uint32_t>(1) << 16,
  513. static_cast<uint32_t>(1) << 25,
  514. static_cast<uint32_t>(1) << 31,
  515. };
  516. int64_t i64s[] = {
  517. -(static_cast<int64_t>(1) << 32),
  518. static_cast<int64_t>(1) << 50,
  519. -(static_cast<int64_t>(1) << 62),
  520. };
  521. uint64_t u64s[] = {
  522. static_cast<uint64_t>(1) << 32,
  523. static_cast<uint64_t>(1) << 50,
  524. static_cast<uint64_t>(1) << 63,
  525. };
  526. } // namespace conv_bench_detail
  527. } // namespace folly
  528. BENCHMARK(preallocateTestInt8, n) {
  529. for (size_t i = 0; i < n; ++i) {
  530. doNotOptimizeAway(to<std::string>(
  531. i8s[0],
  532. ',',
  533. u8s[0],
  534. ',',
  535. i8s[1],
  536. ',',
  537. u8s[1],
  538. ',',
  539. i8s[2],
  540. ',',
  541. u8s[2])
  542. .size());
  543. }
  544. }
  545. BENCHMARK(preallocateTestInt16, n) {
  546. for (size_t i = 0; i < n; ++i) {
  547. doNotOptimizeAway(to<std::string>(
  548. i16s[0],
  549. ',',
  550. u16s[0],
  551. ',',
  552. i16s[1],
  553. ',',
  554. u16s[1],
  555. ',',
  556. i16s[2],
  557. ',',
  558. u16s[2])
  559. .size());
  560. }
  561. }
  562. BENCHMARK(preallocateTestInt32, n) {
  563. for (size_t i = 0; i < n; ++i) {
  564. doNotOptimizeAway(to<std::string>(
  565. i32s[0],
  566. ',',
  567. u32s[0],
  568. ',',
  569. i32s[1],
  570. ',',
  571. u32s[1],
  572. ',',
  573. i32s[2],
  574. ',',
  575. u32s[2])
  576. .size());
  577. }
  578. }
  579. BENCHMARK(preallocateTestInt64, n) {
  580. for (size_t i = 0; i < n; ++i) {
  581. doNotOptimizeAway(to<std::string>(
  582. i64s[0],
  583. ',',
  584. u64s[0],
  585. ',',
  586. i64s[1],
  587. ',',
  588. u64s[1],
  589. ',',
  590. i64s[2],
  591. ',',
  592. u64s[2])
  593. .size());
  594. }
  595. }
  596. #if FOLLY_HAVE_INT128_T
  597. namespace {
  598. __int128 i128s[] = {
  599. -(static_cast<__int128>(1) << 2),
  600. static_cast<__int128>(1) << 100,
  601. -(static_cast<__int128>(1) << 126),
  602. };
  603. unsigned __int128 u128s[] = {
  604. static_cast<unsigned __int128>(1) << 2,
  605. static_cast<unsigned __int128>(1) << 100,
  606. static_cast<unsigned __int128>(1) << 127,
  607. };
  608. } // namespace
  609. BENCHMARK(preallocateTestInt128, n) {
  610. for (size_t i = 0; i < n; ++i) {
  611. doNotOptimizeAway(to<std::string>(
  612. i128s[0],
  613. ',',
  614. u128s[0],
  615. ',',
  616. i128s[1],
  617. ',',
  618. u128s[1],
  619. ',',
  620. i128s[2],
  621. ',',
  622. u128s[2])
  623. .size());
  624. }
  625. }
  626. BENCHMARK(preallocateTestNoFloatWithInt128, n) {
  627. for (size_t i = 0; i < n; ++i) {
  628. doNotOptimizeAway(
  629. to<std::string>(bigInt, someString, stdString, otherString).size());
  630. doNotOptimizeAway(
  631. to<std::string>(reallyShort, u128s[0], smallInt, i128s[2]).size());
  632. doNotOptimizeAway(
  633. to<std::string>(bigInt, i128s[0], stdString, u128s[1]).size());
  634. doNotOptimizeAway(
  635. to<std::string>(bigInt, stdString, dValue, otherString).size());
  636. doNotOptimizeAway(
  637. to<std::string>(bigInt, u128s[2], someString, reallyShort).size());
  638. }
  639. }
  640. #endif
  641. BENCHMARK_DRAW_LINE();
  642. static const StringIdenticalToBM<std::string> stringIdenticalToBM;
  643. static const StringVariadicToBM<std::string> stringVariadicToBM;
  644. static const StringIdenticalToBM<fbstring> fbstringIdenticalToBM;
  645. static const StringVariadicToBM<fbstring> fbstringVariadicToBM;
  646. #define DEFINE_BENCHMARK_GROUP(n) \
  647. BENCHMARK_PARAM(u64ToAsciiClassicBM, n) \
  648. BENCHMARK_RELATIVE_PARAM(u64ToAsciiTableBM, n) \
  649. BENCHMARK_RELATIVE_PARAM(u64ToAsciiFollyBM, n) \
  650. BENCHMARK_DRAW_LINE()
  651. DEFINE_BENCHMARK_GROUP(1);
  652. DEFINE_BENCHMARK_GROUP(2);
  653. DEFINE_BENCHMARK_GROUP(3);
  654. DEFINE_BENCHMARK_GROUP(4);
  655. DEFINE_BENCHMARK_GROUP(5);
  656. DEFINE_BENCHMARK_GROUP(6);
  657. DEFINE_BENCHMARK_GROUP(7);
  658. DEFINE_BENCHMARK_GROUP(8);
  659. DEFINE_BENCHMARK_GROUP(9);
  660. DEFINE_BENCHMARK_GROUP(10);
  661. DEFINE_BENCHMARK_GROUP(11);
  662. DEFINE_BENCHMARK_GROUP(12);
  663. DEFINE_BENCHMARK_GROUP(13);
  664. DEFINE_BENCHMARK_GROUP(14);
  665. DEFINE_BENCHMARK_GROUP(15);
  666. DEFINE_BENCHMARK_GROUP(16);
  667. DEFINE_BENCHMARK_GROUP(17);
  668. DEFINE_BENCHMARK_GROUP(18);
  669. DEFINE_BENCHMARK_GROUP(19);
  670. DEFINE_BENCHMARK_GROUP(20);
  671. #undef DEFINE_BENCHMARK_GROUP
  672. #define DEFINE_BENCHMARK_GROUP(n) \
  673. BENCHMARK_PARAM(u64ToStringClibMeasure, n) \
  674. BENCHMARK_RELATIVE_PARAM(u64ToStringFollyMeasure, n) \
  675. BENCHMARK_RELATIVE_PARAM(i64ToStringFollyMeasurePos, n) \
  676. BENCHMARK_RELATIVE_PARAM(i64ToStringFollyMeasureNeg, n) \
  677. BENCHMARK_DRAW_LINE()
  678. DEFINE_BENCHMARK_GROUP(1);
  679. DEFINE_BENCHMARK_GROUP(2);
  680. DEFINE_BENCHMARK_GROUP(3);
  681. DEFINE_BENCHMARK_GROUP(4);
  682. DEFINE_BENCHMARK_GROUP(5);
  683. DEFINE_BENCHMARK_GROUP(6);
  684. DEFINE_BENCHMARK_GROUP(7);
  685. DEFINE_BENCHMARK_GROUP(8);
  686. DEFINE_BENCHMARK_GROUP(9);
  687. DEFINE_BENCHMARK_GROUP(10);
  688. DEFINE_BENCHMARK_GROUP(11);
  689. DEFINE_BENCHMARK_GROUP(12);
  690. DEFINE_BENCHMARK_GROUP(13);
  691. DEFINE_BENCHMARK_GROUP(14);
  692. DEFINE_BENCHMARK_GROUP(15);
  693. DEFINE_BENCHMARK_GROUP(16);
  694. DEFINE_BENCHMARK_GROUP(17);
  695. DEFINE_BENCHMARK_GROUP(18);
  696. DEFINE_BENCHMARK_GROUP(19);
  697. // Only for u64
  698. BENCHMARK_PARAM(u64ToStringClibMeasure, 20)
  699. BENCHMARK_RELATIVE_PARAM(u64ToStringFollyMeasure, 20)
  700. BENCHMARK_DRAW_LINE();
  701. #undef DEFINE_BENCHMARK_GROUP
  702. #if FOLLY_HAVE_INT128_T
  703. void u128ToStringFollyMeasure(unsigned int n, size_t index) {
  704. checkArrayIndex(uint128Num, index);
  705. FOR_EACH_RANGE (i, 0, n) {
  706. doNotOptimizeAway(to<std::string>(uint128Num[index] + (i % 8)).size());
  707. }
  708. }
  709. void i128ToStringFollyMeasurePos(unsigned int n, size_t index) {
  710. checkArrayIndex(int128Pos, index);
  711. FOR_EACH_RANGE (i, 0, n) {
  712. doNotOptimizeAway(to<std::string>(int128Pos[index] + (i % 8)).size());
  713. }
  714. }
  715. void i128ToStringFollyMeasureNeg(unsigned int n, size_t index) {
  716. checkArrayIndex(int128Neg, index);
  717. FOR_EACH_RANGE (i, 0, n) {
  718. doNotOptimizeAway(to<std::string>(int128Neg[index] + (i % 8)).size());
  719. }
  720. }
  721. #define DEFINE_BENCHMARK_GROUP(n) \
  722. BENCHMARK_PARAM(u128ToStringFollyMeasure, n) \
  723. BENCHMARK_RELATIVE_PARAM(i128ToStringFollyMeasurePos, n) \
  724. BENCHMARK_RELATIVE_PARAM(i128ToStringFollyMeasureNeg, n) \
  725. BENCHMARK_DRAW_LINE()
  726. DEFINE_BENCHMARK_GROUP(1);
  727. DEFINE_BENCHMARK_GROUP(2);
  728. DEFINE_BENCHMARK_GROUP(3);
  729. DEFINE_BENCHMARK_GROUP(4);
  730. DEFINE_BENCHMARK_GROUP(5);
  731. DEFINE_BENCHMARK_GROUP(6);
  732. DEFINE_BENCHMARK_GROUP(7);
  733. DEFINE_BENCHMARK_GROUP(8);
  734. DEFINE_BENCHMARK_GROUP(9);
  735. DEFINE_BENCHMARK_GROUP(10);
  736. DEFINE_BENCHMARK_GROUP(11);
  737. DEFINE_BENCHMARK_GROUP(12);
  738. DEFINE_BENCHMARK_GROUP(13);
  739. DEFINE_BENCHMARK_GROUP(14);
  740. DEFINE_BENCHMARK_GROUP(15);
  741. DEFINE_BENCHMARK_GROUP(16);
  742. DEFINE_BENCHMARK_GROUP(17);
  743. DEFINE_BENCHMARK_GROUP(18);
  744. DEFINE_BENCHMARK_GROUP(19);
  745. DEFINE_BENCHMARK_GROUP(20);
  746. DEFINE_BENCHMARK_GROUP(21);
  747. DEFINE_BENCHMARK_GROUP(22);
  748. DEFINE_BENCHMARK_GROUP(23);
  749. DEFINE_BENCHMARK_GROUP(24);
  750. DEFINE_BENCHMARK_GROUP(25);
  751. DEFINE_BENCHMARK_GROUP(26);
  752. DEFINE_BENCHMARK_GROUP(27);
  753. DEFINE_BENCHMARK_GROUP(28);
  754. DEFINE_BENCHMARK_GROUP(29);
  755. DEFINE_BENCHMARK_GROUP(30);
  756. DEFINE_BENCHMARK_GROUP(31);
  757. DEFINE_BENCHMARK_GROUP(32);
  758. DEFINE_BENCHMARK_GROUP(33);
  759. DEFINE_BENCHMARK_GROUP(34);
  760. DEFINE_BENCHMARK_GROUP(35);
  761. DEFINE_BENCHMARK_GROUP(36);
  762. DEFINE_BENCHMARK_GROUP(37);
  763. DEFINE_BENCHMARK_GROUP(38);
  764. DEFINE_BENCHMARK_GROUP(39);
  765. BENCHMARK_DRAW_LINE();
  766. #undef DEFINE_BENCHMARK_GROUP
  767. #endif
  768. #define DEFINE_BENCHMARK_GROUP(n) \
  769. BENCHMARK_PARAM(clibAtoiMeasure, n) \
  770. BENCHMARK_RELATIVE_PARAM(lexicalCastMeasure, n) \
  771. BENCHMARK_RELATIVE_PARAM(handwrittenAtoiMeasure, n) \
  772. BENCHMARK_RELATIVE_PARAM(follyAtoiMeasure, n) \
  773. BENCHMARK_DRAW_LINE()
  774. DEFINE_BENCHMARK_GROUP(1);
  775. DEFINE_BENCHMARK_GROUP(2);
  776. DEFINE_BENCHMARK_GROUP(3);
  777. DEFINE_BENCHMARK_GROUP(4);
  778. DEFINE_BENCHMARK_GROUP(5);
  779. DEFINE_BENCHMARK_GROUP(6);
  780. DEFINE_BENCHMARK_GROUP(7);
  781. DEFINE_BENCHMARK_GROUP(8);
  782. DEFINE_BENCHMARK_GROUP(9);
  783. DEFINE_BENCHMARK_GROUP(10);
  784. DEFINE_BENCHMARK_GROUP(11);
  785. DEFINE_BENCHMARK_GROUP(12);
  786. DEFINE_BENCHMARK_GROUP(13);
  787. DEFINE_BENCHMARK_GROUP(14);
  788. DEFINE_BENCHMARK_GROUP(15);
  789. DEFINE_BENCHMARK_GROUP(16);
  790. DEFINE_BENCHMARK_GROUP(17);
  791. DEFINE_BENCHMARK_GROUP(18);
  792. DEFINE_BENCHMARK_GROUP(19);
  793. #undef DEFINE_BENCHMARK_GROUP
  794. #define DEFINE_BENCHMARK_GROUP(T, n) \
  795. BENCHMARK_PARAM(T##VariadicToBM, n) \
  796. BENCHMARK_RELATIVE_PARAM(T##IdenticalToBM, n) \
  797. BENCHMARK_DRAW_LINE()
  798. DEFINE_BENCHMARK_GROUP(string, 32);
  799. DEFINE_BENCHMARK_GROUP(string, 1024);
  800. DEFINE_BENCHMARK_GROUP(string, 32768);
  801. DEFINE_BENCHMARK_GROUP(fbstring, 32);
  802. DEFINE_BENCHMARK_GROUP(fbstring, 1024);
  803. DEFINE_BENCHMARK_GROUP(fbstring, 32768);
  804. #undef DEFINE_BENCHMARK_GROUP
  805. namespace {
  806. template <typename T>
  807. inline void stringToTypeClassic(const char* str, uint32_t n) {
  808. for (uint32_t i = 0; i < n; ++i) {
  809. try {
  810. auto val = to<T>(str);
  811. doNotOptimizeAway(val);
  812. } catch (const std::exception& e) {
  813. doNotOptimizeAway(e.what());
  814. }
  815. doNotOptimizeAway(i);
  816. }
  817. }
  818. template <typename T>
  819. inline void stringToTypeOptional(const char* str, uint32_t n) {
  820. for (uint32_t i = 0; i < n; ++i) {
  821. auto val = tryTo<T>(str);
  822. if (val.hasValue()) {
  823. doNotOptimizeAway(val.value());
  824. }
  825. }
  826. }
  827. template <typename T>
  828. inline void ptrPairToIntClassic(StringPiece sp, uint32_t n) {
  829. for (uint32_t i = 0; i < n; ++i) {
  830. try {
  831. auto val = to<T>(sp.begin(), sp.end());
  832. doNotOptimizeAway(val);
  833. } catch (const std::exception& e) {
  834. doNotOptimizeAway(e.what());
  835. }
  836. doNotOptimizeAway(i);
  837. }
  838. }
  839. template <typename T>
  840. inline void ptrPairToIntOptional(StringPiece sp, uint32_t n) {
  841. for (uint32_t i = 0; i < n; ++i) {
  842. auto val = tryTo<T>(sp.begin(), sp.end());
  843. if (val.hasValue()) {
  844. doNotOptimizeAway(val.value());
  845. }
  846. }
  847. }
  848. constexpr uint32_t kArithNumIter = 10000;
  849. template <typename T, typename U>
  850. inline size_t arithToArithClassic(const U* in, uint32_t numItems) {
  851. for (uint32_t i = 0; i < kArithNumIter; ++i) {
  852. for (uint32_t j = 0; j < numItems; ++j) {
  853. try {
  854. auto val = to<T>(in[j]);
  855. doNotOptimizeAway(val);
  856. } catch (const std::exception& e) {
  857. doNotOptimizeAway(e.what());
  858. }
  859. doNotOptimizeAway(j);
  860. }
  861. doNotOptimizeAway(i);
  862. }
  863. return kArithNumIter * numItems;
  864. }
  865. template <typename T, typename U>
  866. inline size_t arithToArithOptional(const U* in, uint32_t numItems) {
  867. for (uint32_t i = 0; i < kArithNumIter; ++i) {
  868. for (uint32_t j = 0; j < numItems; ++j) {
  869. auto val = tryTo<T>(*in);
  870. doNotOptimizeAway(val.hasValue());
  871. if (val.hasValue()) {
  872. auto v2 = val.value();
  873. doNotOptimizeAway(v2);
  874. }
  875. doNotOptimizeAway(j);
  876. }
  877. doNotOptimizeAway(i);
  878. }
  879. return kArithNumIter * numItems;
  880. }
  881. } // namespace
  882. namespace folly {
  883. namespace conv_bench_detail {
  884. // Keep this data global and non-const, so the compiler cannot make
  885. // any assumptions about the actual values at compile time
  886. std::array<int, 4> int2ScharGood{{-128, 127, 0, -50}};
  887. std::array<int, 4> int2ScharBad{{-129, 128, 255, 10000}};
  888. std::array<int, 4> int2UcharGood{{0, 1, 254, 255}};
  889. std::array<int, 4> int2UcharBad{{-128, -1000, 256, -1}};
  890. std::array<long long, 4> ll2SintOrFloatGood{{-2, -1, 0, 1}};
  891. std::array<long long, 4> ll2SintOrFloatBad{{
  892. std::numeric_limits<long long>::min() / 5,
  893. std::numeric_limits<long long>::min() / 2,
  894. std::numeric_limits<long long>::max() / 2,
  895. std::numeric_limits<long long>::max() / 5,
  896. }};
  897. std::array<long long, 4> ll2UintGood{{1, 2, 3, 4}};
  898. std::array<long long, 4> ll2UintBad{{-1, -2, -3, -4}};
  899. std::array<double, 4> double2FloatGood{{1.0, 1.25, 2.5, 1000.0}};
  900. std::array<double, 4> double2FloatBad{{1e100, 1e101, 1e102, 1e103}};
  901. std::array<double, 4> double2IntGood{{1.0, 10.0, 100.0, 1000.0}};
  902. std::array<double, 4> double2IntBad{{1e100, 1.25, 2.5, 100.00001}};
  903. } // namespace conv_bench_detail
  904. } // namespace folly
  905. #define STRING_TO_TYPE_BENCHMARK(type, name, pass, fail) \
  906. BENCHMARK(stringTo##name##Classic, n) { \
  907. stringToTypeClassic<type>(pass, n); \
  908. } \
  909. BENCHMARK(stringTo##name##ClassicError, n) { \
  910. stringToTypeClassic<type>(fail, n); \
  911. } \
  912. BENCHMARK(stringTo##name##Optional, n) { \
  913. stringToTypeOptional<type>(pass, n); \
  914. } \
  915. BENCHMARK(stringTo##name##OptionalError, n) { \
  916. stringToTypeOptional<type>(fail, n); \
  917. }
  918. #define PTR_PAIR_TO_INT_BENCHMARK(type, name, pass, fail) \
  919. BENCHMARK(ptrPairTo##name##Classic, n) { \
  920. ptrPairToIntClassic<type>(pass, n); \
  921. } \
  922. BENCHMARK(ptrPairTo##name##ClassicError, n) { \
  923. ptrPairToIntClassic<type>(fail, n); \
  924. } \
  925. BENCHMARK(ptrPairTo##name##Optional, n) { \
  926. ptrPairToIntOptional<type>(pass, n); \
  927. } \
  928. BENCHMARK(ptrPairTo##name##OptionalError, n) { \
  929. ptrPairToIntOptional<type>(fail, n); \
  930. }
  931. #define ARITH_TO_ARITH_BENCHMARK(type, name, pass, fail) \
  932. BENCHMARK_MULTI(name##Classic) { \
  933. return arithToArithClassic<type>(pass.data(), pass.size()); \
  934. } \
  935. BENCHMARK_MULTI(name##ClassicError) { \
  936. return arithToArithClassic<type>(fail.data(), fail.size()); \
  937. } \
  938. BENCHMARK_MULTI(name##Optional) { \
  939. return arithToArithOptional<type>(pass.data(), pass.size()); \
  940. } \
  941. BENCHMARK_MULTI(name##OptionalError) { \
  942. return arithToArithOptional<type>(fail.data(), fail.size()); \
  943. }
  944. #define INT_TO_ARITH_BENCHMARK(type, name, pass, fail) \
  945. ARITH_TO_ARITH_BENCHMARK(type, intTo##name, pass, fail)
  946. #define FLOAT_TO_ARITH_BENCHMARK(type, name, pass, fail) \
  947. ARITH_TO_ARITH_BENCHMARK(type, floatTo##name, pass, fail)
  948. STRING_TO_TYPE_BENCHMARK(bool, BoolNum, " 1 ", "2")
  949. STRING_TO_TYPE_BENCHMARK(bool, BoolStr, "true", "xxxx")
  950. BENCHMARK_DRAW_LINE();
  951. STRING_TO_TYPE_BENCHMARK(float, FloatNum, " 3.14 ", "3e5000x")
  952. STRING_TO_TYPE_BENCHMARK(float, FloatStr, "-infinity", "xxxx")
  953. STRING_TO_TYPE_BENCHMARK(double, DoubleNum, " 3.14 ", "3e5000x")
  954. STRING_TO_TYPE_BENCHMARK(double, DoubleStr, "-infinity", "xxxx")
  955. BENCHMARK_DRAW_LINE();
  956. STRING_TO_TYPE_BENCHMARK(signed char, CharSigned, " -47 ", "1000")
  957. STRING_TO_TYPE_BENCHMARK(unsigned char, CharUnsigned, " 47 ", "-47")
  958. STRING_TO_TYPE_BENCHMARK(int, IntSigned, " -4711 ", "-10000000000000000000000")
  959. STRING_TO_TYPE_BENCHMARK(unsigned int, IntUnsigned, " 4711 ", "-4711")
  960. STRING_TO_TYPE_BENCHMARK(
  961. long long,
  962. LongLongSigned,
  963. " -8123456789123456789 ",
  964. "-10000000000000000000000")
  965. STRING_TO_TYPE_BENCHMARK(
  966. unsigned long long,
  967. LongLongUnsigned,
  968. " 18123456789123456789 ",
  969. "-4711")
  970. BENCHMARK_DRAW_LINE();
  971. PTR_PAIR_TO_INT_BENCHMARK(signed char, CharSigned, "-47", "1000")
  972. PTR_PAIR_TO_INT_BENCHMARK(unsigned char, CharUnsigned, "47", "1000")
  973. PTR_PAIR_TO_INT_BENCHMARK(int, IntSigned, "-4711", "-10000000000000000000000")
  974. PTR_PAIR_TO_INT_BENCHMARK(
  975. unsigned int,
  976. IntUnsigned,
  977. "4711",
  978. "10000000000000000000000")
  979. PTR_PAIR_TO_INT_BENCHMARK(
  980. long long,
  981. LongLongSigned,
  982. "-8123456789123456789",
  983. "-10000000000000000000000")
  984. PTR_PAIR_TO_INT_BENCHMARK(
  985. unsigned long long,
  986. LongLongUnsigned,
  987. "18123456789123456789",
  988. "20000000000000000000")
  989. BENCHMARK_DRAW_LINE();
  990. INT_TO_ARITH_BENCHMARK(signed char, CharSigned, int2ScharGood, int2ScharBad)
  991. INT_TO_ARITH_BENCHMARK(unsigned char, CharUnsigned, int2UcharGood, int2UcharBad)
  992. INT_TO_ARITH_BENCHMARK(int, IntSigned, ll2SintOrFloatGood, ll2SintOrFloatBad)
  993. INT_TO_ARITH_BENCHMARK(unsigned int, IntUnsigned, ll2UintGood, ll2UintBad)
  994. BENCHMARK_DRAW_LINE();
  995. INT_TO_ARITH_BENCHMARK(float, Float, ll2SintOrFloatGood, ll2SintOrFloatBad)
  996. BENCHMARK_DRAW_LINE();
  997. FLOAT_TO_ARITH_BENCHMARK(float, Float, double2FloatGood, double2FloatBad)
  998. BENCHMARK_DRAW_LINE();
  999. FLOAT_TO_ARITH_BENCHMARK(int, Int, double2IntGood, double2IntBad)
  1000. #undef STRING_TO_TYPE_BENCHMARK
  1001. #undef PTR_PAIR_TO_INT_BENCHMARK
  1002. #undef ARITH_TO_ARITH_BENCHMARK
  1003. #undef INT_TO_ARITH_BENCHMARK
  1004. #undef FLOAT_TO_ARITH_BENCHMARK
  1005. int main(int argc, char** argv) {
  1006. gflags::ParseCommandLineFlags(&argc, &argv, true);
  1007. folly::runBenchmarks();
  1008. return 0;
  1009. }