Commit 241ea7bd authored by Chip Turner's avatar Chip Turner Committed by Facebook Github Bot

Add benchmarks similar to `stringPrintf` for `folly::Format` and `fmt`

Summary:
Basic benchmarks to validate performance of similar string
formatting functions.  Notably, `stringPrintf` is always inferior to
either format-based alternative.

```
============================================================================
folly/test/StringBenchmark.cpp                  relative  time/iter  iters/s
============================================================================
libc_tolower                                               714.38ns    1.40M
folly_toLowerAscii                                          66.03ns   15.14M
stringPrintfOutputSize(1)                                  170.06ns    5.88M
stringPrintfOutputSize(4)                                  198.54ns    5.04M
stringPrintfOutputSize(16)                                 202.94ns    4.93M
stringPrintfOutputSize(64)                                 204.82ns    4.88M
stringPrintfOutputSize(256)                                  1.32us  759.95K
stringPrintfOutputSize(1024)                                 4.47us  223.70K
stringPrintfAppendfBenchmark                                25.38ms    39.40
fmtOutputSize(1)                                           104.62ns    9.56M
fmtOutputSize(4)                                           121.50ns    8.23M
fmtOutputSize(16)                                          125.27ns    7.98M
fmtOutputSize(64)                                          125.59ns    7.96M
fmtOutputSize(256)                                         633.15ns    1.58M
fmtOutputSize(1024)                                          1.06us  939.38K
fmtAppendfBenchmark                                          8.22ms   121.71
follyFmtOutputSize(1)                                      122.76ns    8.15M
follyFmtOutputSize(4)                                      149.51ns    6.69M
follyFmtOutputSize(16)                                     148.90ns    6.72M
follyFmtOutputSize(64)                                     147.45ns    6.78M
follyFmtOutputSize(256)                                    150.71ns    6.64M
follyFmtOutputSize(1024)                                   584.94ns    1.71M
follyFmtAppendfBenchmark                                    11.39ms    87.79
BM_cEscape                                                 321.10us    3.11K
BM_cUnescape                                               290.97us    3.44K
BM_uriEscape                                                 2.99us  333.92K
BM_uriUnescape                                               1.56us  639.36K
BM_unhexlify                                               525.33ps    1.90G
splitOnSingleChar                                            1.21us  823.13K
splitOnSingleCharFixed                                     466.79ns    2.14M
splitOnSingleCharFixedAllowExtra                             0.00fs  Infinity
splitStr                                                     1.86us  536.53K
splitStrFixed                                              620.41ns    1.61M
boost_splitOnSingleChar                                      2.34us  427.23K
joinCharStr                                                947.58ns    1.06M
joinStrStr                                                 956.37ns    1.05M
joinInt                                                      2.24us  447.21K
============================================================================
```

Reviewed By: vitaut

Differential Revision: D13940303

fbshipit-source-id: a26d984cde26b1a5eb3eba1935722cdcd221fe44
parent 5aaeba16
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
#include <fmt/format.h>
#include <folly/Format.h>
#include <folly/String.h> #include <folly/String.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
...@@ -56,6 +58,7 @@ BENCHMARK(folly_toLowerAscii, iters) { ...@@ -56,6 +58,7 @@ BENCHMARK(folly_toLowerAscii, iters) {
// A simple benchmark that tests various output sizes for a simple // A simple benchmark that tests various output sizes for a simple
// input; the goal is to measure the output buffer resize code cost. // input; the goal is to measure the output buffer resize code cost.
const size_t kAppendBufSize = 300000;
void stringPrintfOutputSize(int iters, int param) { void stringPrintfOutputSize(int iters, int param) {
string buffer; string buffer;
BENCHMARK_SUSPEND { BENCHMARK_SUSPEND {
...@@ -80,14 +83,91 @@ BENCHMARK_PARAM(stringPrintfOutputSize, 1024) ...@@ -80,14 +83,91 @@ BENCHMARK_PARAM(stringPrintfOutputSize, 1024)
// Benchmark simple stringAppendf behavior to show a pathology Lovro // Benchmark simple stringAppendf behavior to show a pathology Lovro
// reported (t5735468). // reported (t5735468).
BENCHMARK(stringPrintfAppendfBenchmark, iters) { BENCHMARK(stringPrintfAppendfBenchmark, iters) {
for (unsigned int i = 0; i < iters; ++i) { for (size_t i = 0; i < iters; ++i) {
string s; string s;
BENCHMARK_SUSPEND { BENCHMARK_SUSPEND {
s.reserve(300000); s.reserve(kAppendBufSize);
} }
for (int j = 0; j < 300000; ++j) { for (size_t j = 0; j < kAppendBufSize; ++j) {
stringAppendf(&s, "%d", 1); stringAppendf(&s, "%d", 1);
} }
DCHECK_EQ(s.size(), kAppendBufSize);
}
}
// A simple benchmark that tests various output sizes for a simple
// input; the goal is to measure the output buffer resize code cost.
// Intended for comparison with stringPrintf.
void fmtOutputSize(int iters, int param) {
string buffer;
BENCHMARK_SUSPEND {
buffer.resize(param, 'x');
}
for (int64_t i = 0; i < iters; ++i) {
string s = fmt::format("msg: {}, {}, {}", 10, 20, buffer);
}
}
// The first few of these tend to fit in the inline buffer, while the
// subsequent ones cross that limit, trigger a second vsnprintf, and
// exercise a different codepath.
BENCHMARK_PARAM(fmtOutputSize, 1)
BENCHMARK_PARAM(fmtOutputSize, 4)
BENCHMARK_PARAM(fmtOutputSize, 16)
BENCHMARK_PARAM(fmtOutputSize, 64)
BENCHMARK_PARAM(fmtOutputSize, 256)
BENCHMARK_PARAM(fmtOutputSize, 1024)
// Benchmark simple fmt append behavior; intended as a comparison
// against stringAppendf.
BENCHMARK(fmtAppendfBenchmark, iters) {
for (size_t i = 0; i < iters; ++i) {
fmt::memory_buffer buf;
for (size_t j = 0; j < kAppendBufSize; ++j) {
fmt::format_to(buf, "{}", 1);
}
string s = fmt::to_string(buf);
DCHECK_EQ(s.size(), kAppendBufSize);
}
}
// A simple benchmark that tests various output sizes for a simple
// input; the goal is to measure the output buffer resize code cost.
// Intended for comparison with stringPrintf and fmt.
void follyFmtOutputSize(int iters, int param) {
string buffer;
BENCHMARK_SUSPEND {
buffer.resize(param, 'x');
}
for (int64_t i = 0; i < iters; ++i) {
string s = format("msg: {}, {}, {}", 10, 20, buffer).str();
}
}
// The first few of these tend to fit in the inline buffer, while the
// subsequent ones cross that limit, trigger a second vsnprintf, and
// exercise a different codepath.
BENCHMARK_PARAM(follyFmtOutputSize, 1)
BENCHMARK_PARAM(follyFmtOutputSize, 4)
BENCHMARK_PARAM(follyFmtOutputSize, 16)
BENCHMARK_PARAM(follyFmtOutputSize, 64)
BENCHMARK_PARAM(follyFmtOutputSize, 256)
BENCHMARK_PARAM(follyFmtOutputSize, 1024)
// Benchmark simple fmt append behavior; intended as a comparison
// against stringAppendf.
BENCHMARK(follyFmtAppendfBenchmark, iters) {
for (size_t i = 0; i < iters; ++i) {
string s;
BENCHMARK_SUSPEND {
s.reserve(kAppendBufSize);
}
for (size_t j = 0; j < kAppendBufSize; ++j) {
format("{}", 1).appendTo(s);
}
DCHECK_EQ(s.size(), kAppendBufSize);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment