add missing include to ThreadId.h
[folly.git] / folly / test / FormatBenchmark.cpp
1 /*
2  * Copyright 2017 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/Format.h>
18
19 #include <glog/logging.h>
20
21 #include <folly/Benchmark.h>
22 #include <folly/FBVector.h>
23 #include <folly/dynamic.h>
24 #include <folly/init/Init.h>
25 #include <folly/json.h>
26
27 using namespace folly;
28
29 namespace {
30
31 std::array<char, 300> bigBuf;
32
33 std::string getShortString() {
34   return "ABCDEFGHIJ";
35 }
36
37 std::string getLongString() {
38   return std::string(256, 'A');
39 }
40
41 } // namespace
42
43 BENCHMARK(octal_snprintf, iters) {
44   while (iters--) {
45     snprintf(
46         bigBuf.data(), bigBuf.size(), "%o", static_cast<unsigned int>(iters));
47   }
48 }
49
50 BENCHMARK_RELATIVE(octal_uintToOctal, iters) {
51   while (iters--) {
52     detail::uintToOctal(
53         bigBuf.data(),
54         detail::kMaxOctalLength,
55         static_cast<unsigned int>(iters));
56   }
57 }
58
59 BENCHMARK_DRAW_LINE()
60
61 BENCHMARK(hex_snprintf, iters) {
62   while (iters--) {
63     snprintf(
64         bigBuf.data(), bigBuf.size(), "%x", static_cast<unsigned int>(iters));
65   }
66 }
67
68 BENCHMARK_RELATIVE(hex_uintToHex, iters) {
69   while (iters--) {
70     detail::uintToHexLower(
71         bigBuf.data(), detail::kMaxHexLength, static_cast<unsigned int>(iters));
72   }
73 }
74
75 BENCHMARK_DRAW_LINE()
76
77 BENCHMARK(intAppend_snprintf) {
78   fbstring out;
79   for (int i = -1000; i < 1000; i++) {
80     snprintf(bigBuf.data(), bigBuf.size(), "%d", i);
81     out.append(bigBuf.data());
82   }
83 }
84
85 BENCHMARK_RELATIVE(intAppend_to) {
86   fbstring out;
87   for (int i = -1000; i < 1000; i++) {
88     toAppend(i, &out);
89   }
90 }
91
92 BENCHMARK_RELATIVE(intAppend_format) {
93   fbstring out;
94   for (int i = -1000; i < 1000; i++) {
95     format(&out, "{}", i);
96   }
97 }
98
99 BENCHMARK_DRAW_LINE()
100
101 template <size_t... Indexes>
102 int snprintf20Numbers(int i, std::index_sequence<Indexes...>) {
103   static_assert(20 == sizeof...(Indexes), "Must have exactly 20 indexes");
104   return snprintf(
105       bigBuf.data(),
106       bigBuf.size(),
107       "%d %d %d %d %d"
108       "%d %d %d %d %d"
109       "%d %d %d %d %d"
110       "%d %d %d %d %d",
111       (i + static_cast<int>(Indexes))...);
112 }
113
114 BENCHMARK(bigFormat_snprintf, iters) {
115   while (iters--) {
116     for (int i = -100; i < 100; i++) {
117       snprintf20Numbers(i, std::make_index_sequence<20>());
118     }
119   }
120 }
121
122 template <size_t... Indexes>
123 decltype(auto) format20Numbers(int i, std::index_sequence<Indexes...>) {
124   static_assert(20 == sizeof...(Indexes), "Must have exactly 20 indexes");
125   return format(
126       "{} {} {} {} {}"
127       "{} {} {} {} {}"
128       "{} {} {} {} {}"
129       "{} {} {} {} {}",
130       (i + static_cast<int>(Indexes))...);
131 }
132
133 BENCHMARK_RELATIVE(bigFormat_format, iters) {
134   BenchmarkSuspender suspender;
135   char* p;
136   auto writeToBuf = [&p](StringPiece sp) mutable {
137     memcpy(p, sp.data(), sp.size());
138     p += sp.size();
139   };
140
141   while (iters--) {
142     for (int i = -100; i < 100; i++) {
143       p = bigBuf.data();
144       suspender.dismissing([&] {
145         format20Numbers(i, std::make_index_sequence<20>())(writeToBuf);
146       });
147     }
148   }
149 }
150
151 BENCHMARK_DRAW_LINE()
152
153 BENCHMARK(format_nested_strings, iters) {
154   BenchmarkSuspender suspender;
155   while (iters--) {
156     for (int i = 0; i < 1000; ++i) {
157       fbstring out;
158       suspender.dismissing([&] {
159         format(
160             &out,
161             "{} {}",
162             format("{} {}", i, i + 1).str(),
163             format("{} {}", -i, -i - 1).str());
164       });
165     }
166   }
167 }
168
169 BENCHMARK_RELATIVE(format_nested_fbstrings, iters) {
170   BenchmarkSuspender suspender;
171   while (iters--) {
172     for (int i = 0; i < 1000; ++i) {
173       fbstring out;
174       suspender.dismissing([&] {
175         format(
176             &out,
177             "{} {}",
178             format("{} {}", i, i + 1).fbstr(),
179             format("{} {}", -i, -i - 1).fbstr());
180       });
181     }
182   }
183 }
184
185 BENCHMARK_RELATIVE(format_nested_direct, iters) {
186   BenchmarkSuspender suspender;
187   while (iters--) {
188     for (int i = 0; i < 1000; ++i) {
189       fbstring out;
190       suspender.dismissing([&] {
191         format(
192             &out,
193             "{} {}",
194             format("{} {}", i, i + 1),
195             format("{} {}", -i, -i - 1));
196       });
197     }
198   }
199 }
200
201 BENCHMARK_DRAW_LINE()
202
203 BENCHMARK(copy_short_string, iters) {
204   BenchmarkSuspender suspender;
205   auto const& shortString = getShortString();
206   while (iters--) {
207     fbstring out;
208     suspender.dismissing([&] { out = shortString; });
209   }
210 }
211
212 BENCHMARK_RELATIVE(format_short_string_unsafe, iters) {
213   BenchmarkSuspender suspender;
214   auto const& shortString = getShortString();
215   while (iters--) {
216     fbstring out;
217     suspender.dismissing([&] { format(&out, shortString); });
218   }
219 }
220
221 BENCHMARK_RELATIVE(format_short_string_safe, iters) {
222   BenchmarkSuspender suspender;
223   auto const& shortString = getShortString();
224   while (iters--) {
225     fbstring out;
226     suspender.dismissing([&] { format(&out, "{}", shortString); });
227   }
228 }
229
230 BENCHMARK_RELATIVE(sformat_short_string_unsafe, iters) {
231   BenchmarkSuspender suspender;
232   auto const& shortString = getShortString();
233   while (iters--) {
234     std::string out;
235     suspender.dismissing([&] { out = sformat(shortString); });
236   }
237 }
238
239 BENCHMARK_RELATIVE(sformat_short_string_safe, iters) {
240   BenchmarkSuspender suspender;
241   auto const& shortString = getShortString();
242   while (iters--) {
243     std::string out;
244     suspender.dismissing([&] { out = sformat("{}", shortString); });
245   }
246 }
247
248 BENCHMARK_DRAW_LINE()
249
250 BENCHMARK(copy_long_string, iters) {
251   BenchmarkSuspender suspender;
252   auto const& longString = getLongString();
253   while (iters--) {
254     fbstring out;
255     suspender.dismissing([&] { out = longString; });
256   }
257 }
258
259 BENCHMARK_RELATIVE(format_long_string_unsafe, iters) {
260   BenchmarkSuspender suspender;
261   auto const& longString = getLongString();
262   while (iters--) {
263     fbstring out;
264     suspender.dismissing([&] { format(&out, longString); });
265   }
266 }
267
268 BENCHMARK_RELATIVE(format_long_string_safe, iters) {
269   BenchmarkSuspender suspender;
270   auto const& longString = getLongString();
271   while (iters--) {
272     fbstring out;
273     suspender.dismissing([&] { format(&out, "{}", longString); });
274   }
275 }
276
277 BENCHMARK_RELATIVE(sformat_long_string_unsafe, iters) {
278   BenchmarkSuspender suspender;
279   auto const& longString = getLongString();
280   while (iters--) {
281     std::string out;
282     suspender.dismissing([&] { out = sformat(longString); });
283   }
284 }
285
286 BENCHMARK_RELATIVE(sformat_long_string_safe, iters) {
287   BenchmarkSuspender suspender;
288   auto const& longString = getLongString();
289   while (iters--) {
290     std::string out;
291     suspender.dismissing([&] { out = sformat("{}", longString); });
292   }
293 }
294
295 // Benchmark results on my dev server (20-core Intel Xeon E5-2660 v2 @ 2.20GHz)
296 //
297 // ============================================================================
298 // folly/test/FormatBenchmark.cpp                  relative  time/iter  iters/s
299 // ============================================================================
300 // octal_snprintf                                              79.30ns   12.61M
301 // octal_uintToOctal                               3452.19%     2.30ns  435.35M
302 // ----------------------------------------------------------------------------
303 // hex_snprintf                                                73.59ns   13.59M
304 // hex_uintToHex                                   4507.53%     1.63ns  612.49M
305 // ----------------------------------------------------------------------------
306 // intAppend_snprintf                                         191.50us    5.22K
307 // intAppend_to                                     552.46%    34.66us   28.85K
308 // intAppend_format                                 215.76%    88.76us   11.27K
309 // ----------------------------------------------------------------------------
310 // bigFormat_snprintf                                         178.03us    5.62K
311 // bigFormat_format                                  90.41%   196.91us    5.08K
312 // ----------------------------------------------------------------------------
313 // format_nested_strings                                      317.65us    3.15K
314 // format_nested_fbstrings                           99.89%   318.01us    3.14K
315 // format_nested_direct                             116.52%   272.62us    3.67K
316 // ----------------------------------------------------------------------------
317 // copy_short_string                                           28.33ns   35.30M
318 // format_short_string_unsafe                        82.51%    34.33ns   29.13M
319 // format_short_string_safe                          58.92%    48.08ns   20.80M
320 // sformat_short_string_unsafe                       73.90%    38.33ns   26.09M
321 // sformat_short_string_safe                         54.97%    51.53ns   19.41M
322 // ----------------------------------------------------------------------------
323 // copy_long_string                                            57.56ns   17.37M
324 // format_long_string_unsafe                         68.79%    83.68ns   11.95M
325 // format_long_string_safe                           69.44%    82.89ns   12.06M
326 // sformat_long_string_unsafe                        65.58%    87.77ns   11.39M
327 // sformat_long_string_safe                          68.14%    84.47ns   11.84M
328 // ============================================================================
329
330 int main(int argc, char* argv[]) {
331   init(&argc, &argv, true);
332   runBenchmarks();
333   return 0;
334 }