Modernise and clang-format existing formatting benchmark
[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 } // namespace
34
35 BENCHMARK(octal_snprintf, iters) {
36   while (iters--) {
37     snprintf(
38         bigBuf.data(), bigBuf.size(), "%o", static_cast<unsigned int>(iters));
39   }
40 }
41
42 BENCHMARK_RELATIVE(octal_uintToOctal, iters) {
43   while (iters--) {
44     detail::uintToOctal(
45         bigBuf.data(),
46         detail::kMaxOctalLength,
47         static_cast<unsigned int>(iters));
48   }
49 }
50
51 BENCHMARK_DRAW_LINE()
52
53 BENCHMARK(hex_snprintf, iters) {
54   while (iters--) {
55     snprintf(
56         bigBuf.data(), bigBuf.size(), "%x", static_cast<unsigned int>(iters));
57   }
58 }
59
60 BENCHMARK_RELATIVE(hex_uintToHex, iters) {
61   while (iters--) {
62     detail::uintToHexLower(
63         bigBuf.data(), detail::kMaxHexLength, static_cast<unsigned int>(iters));
64   }
65 }
66
67 BENCHMARK_DRAW_LINE()
68
69 BENCHMARK(intAppend_snprintf) {
70   fbstring out;
71   for (int i = -1000; i < 1000; i++) {
72     snprintf(bigBuf.data(), bigBuf.size(), "%d", i);
73     out.append(bigBuf.data());
74   }
75 }
76
77 BENCHMARK_RELATIVE(intAppend_to) {
78   fbstring out;
79   for (int i = -1000; i < 1000; i++) {
80     toAppend(i, &out);
81   }
82 }
83
84 BENCHMARK_RELATIVE(intAppend_format) {
85   fbstring out;
86   for (int i = -1000; i < 1000; i++) {
87     format(&out, "{}", i);
88   }
89 }
90
91 BENCHMARK_DRAW_LINE()
92
93 template <size_t... Indexes>
94 int snprintf20Numbers(int i, std::index_sequence<Indexes...>) {
95   static_assert(20 == sizeof...(Indexes), "Must have exactly 20 indexes");
96   return snprintf(
97       bigBuf.data(),
98       bigBuf.size(),
99       "%d %d %d %d %d"
100       "%d %d %d %d %d"
101       "%d %d %d %d %d"
102       "%d %d %d %d %d",
103       (i + static_cast<int>(Indexes))...);
104 }
105
106 BENCHMARK(bigFormat_snprintf, iters) {
107   while (iters--) {
108     for (int i = -100; i < 100; i++) {
109       snprintf20Numbers(i, std::make_index_sequence<20>());
110     }
111   }
112 }
113
114 template <size_t... Indexes>
115 decltype(auto) format20Numbers(int i, std::index_sequence<Indexes...>) {
116   static_assert(20 == sizeof...(Indexes), "Must have exactly 20 indexes");
117   return format(
118       "{} {} {} {} {}"
119       "{} {} {} {} {}"
120       "{} {} {} {} {}"
121       "{} {} {} {} {}",
122       (i + static_cast<int>(Indexes))...);
123 }
124
125 BENCHMARK_RELATIVE(bigFormat_format, iters) {
126   BenchmarkSuspender suspender;
127   char* p;
128   auto writeToBuf = [&p](StringPiece sp) mutable {
129     memcpy(p, sp.data(), sp.size());
130     p += sp.size();
131   };
132
133   while (iters--) {
134     for (int i = -100; i < 100; i++) {
135       p = bigBuf.data();
136       suspender.dismissing([&] {
137         format20Numbers(i, std::make_index_sequence<20>())(writeToBuf);
138       });
139     }
140   }
141 }
142
143 BENCHMARK_DRAW_LINE()
144
145 BENCHMARK(format_nested_strings, iters) {
146   BenchmarkSuspender suspender;
147   while (iters--) {
148     for (int i = 0; i < 1000; ++i) {
149       fbstring out;
150       suspender.dismissing([&]() {
151         format(
152             &out,
153             "{} {}",
154             format("{} {}", i, i + 1).str(),
155             format("{} {}", -i, -i - 1).str());
156       });
157     }
158   }
159 }
160
161 BENCHMARK_RELATIVE(format_nested_fbstrings, iters) {
162   BenchmarkSuspender suspender;
163   while (iters--) {
164     for (int i = 0; i < 1000; ++i) {
165       fbstring out;
166       suspender.dismissing([&] {
167         format(
168             &out,
169             "{} {}",
170             format("{} {}", i, i + 1).fbstr(),
171             format("{} {}", -i, -i - 1).fbstr());
172       });
173     }
174   }
175 }
176
177 BENCHMARK_RELATIVE(format_nested_direct, iters) {
178   BenchmarkSuspender suspender;
179   while (iters--) {
180     for (int i = 0; i < 1000; ++i) {
181       fbstring out;
182       suspender.dismissing([&] {
183         format(
184             &out,
185             "{} {}",
186             format("{} {}", i, i + 1),
187             format("{} {}", -i, -i - 1));
188       });
189     }
190   }
191 }
192
193 // Benchmark results on my dev server (20-core Intel Xeon E5-2660 v2 @ 2.20GHz)
194 //
195 // ============================================================================
196 // folly/test/FormatBenchmark.cpp                  relative  time/iter  iters/s
197 // ============================================================================
198 // octal_snprintf                                              79.30ns   12.61M
199 // octal_uintToOctal                               3452.19%     2.30ns  435.35M
200 // ----------------------------------------------------------------------------
201 // hex_snprintf                                                73.59ns   13.59M
202 // hex_uintToHex                                   4507.53%     1.63ns  612.49M
203 // ----------------------------------------------------------------------------
204 // intAppend_snprintf                                         191.50us    5.22K
205 // intAppend_to                                     552.46%    34.66us   28.85K
206 // intAppend_format                                 215.76%    88.76us   11.27K
207 // ----------------------------------------------------------------------------
208 // bigFormat_snprintf                                         178.03us    5.62K
209 // bigFormat_format                                  90.41%   196.91us    5.08K
210 // ----------------------------------------------------------------------------
211 // format_nested_strings                                      317.65us    3.15K
212 // format_nested_fbstrings                           99.89%   318.01us    3.14K
213 // format_nested_direct                             116.52%   272.62us    3.67K
214 // ============================================================================
215
216 int main(int argc, char* argv[]) {
217   init(&argc, &argv, true);
218   runBenchmarks();
219   return 0;
220 }