2 * Copyright 2016-present Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <folly/io/IOBuf.h>
19 #include <folly/Benchmark.h>
20 #include <folly/Format.h>
21 #include <folly/Range.h>
22 #include <folly/io/Cursor.h>
24 DECLARE_bool(benchmark);
26 using folly::ByteRange;
29 using folly::StringPiece;
30 using std::unique_ptr;
31 using namespace folly::io;
33 int benchmark_size = 1000;
34 unique_ptr<IOBuf> iobuf_benchmark;
36 unique_ptr<IOBuf> iobuf_read_benchmark;
38 template <class CursClass>
40 CursClass c(iobuf_benchmark.get());
42 for (int i = 0; i < benchmark_size; i++) {
47 BENCHMARK(rwPrivateCursorBenchmark, iters) {
49 runBenchmark<RWPrivateCursor>();
53 BENCHMARK(rwUnshareCursorBenchmark, iters) {
55 runBenchmark<RWUnshareCursor>();
59 BENCHMARK(cursorBenchmark, iters) {
61 Cursor c(iobuf_read_benchmark.get());
62 for (int i = 0; i < benchmark_size; i++) {
68 BENCHMARK(skipBenchmark, iters) {
70 Cursor c(iobuf_read_benchmark.get());
71 for (int i = 0; i < benchmark_size; i++) {
78 BENCHMARK(cloneBenchmark, iters) {
81 Cursor c(iobuf_read_benchmark.get());
82 for (int i = 0; i < benchmark_size; ++i) {
88 BENCHMARK(read, iters) {
90 Cursor c(iobuf_read_benchmark.get());
91 for (int i = 0; i < benchmark_size; ++i) {
92 const auto val = c.read<uint8_t>();
93 folly::doNotOptimizeAway(val);
98 BENCHMARK(readSlow, iters) {
100 Cursor c(iobuf_read_benchmark.get());
101 const int size = benchmark_size / 2;
102 for (int i = 0; i < size; ++i) {
103 const auto val = c.read<uint16_t>();
104 folly::doNotOptimizeAway(val);
109 bool prefixBaseline(Cursor& c, const std::array<uint8_t, 4>& expected) {
110 std::array<uint8_t, 4> actual;
111 if (c.pullAtMost(actual.data(), actual.size()) != actual.size()) {
114 return memcmp(actual.data(), expected.data(), actual.size()) == 0;
117 bool prefix(Cursor& c, uint32_t expected) {
119 if (!c.tryReadLE(actual)) {
122 return actual == expected;
125 BENCHMARK(prefixBaseline, iters) {
126 IOBuf buf{IOBuf::CREATE, 10};
128 constexpr std::array<uint8_t, 4> prefix = {{0x01, 0x02, 0x03, 0x04}};
130 for (int i = 0; i < benchmark_size; ++i) {
132 bool result = prefixBaseline(c, prefix);
133 folly::doNotOptimizeAway(result);
138 BENCHMARK_RELATIVE(prefix, iters) {
139 IOBuf buf{IOBuf::CREATE, 10};
142 for (int i = 0; i < benchmark_size; ++i) {
144 bool result = prefix(c, 0x01020304);
145 folly::doNotOptimizeAway(result);
151 * ============================================================================
152 * folly/io/test/IOBufCursorBenchmark.cpp relative time/iter iters/s
153 * ============================================================================
154 * rwPrivateCursorBenchmark 1.01us 985.85K
155 * rwUnshareCursorBenchmark 1.01us 986.70K
156 * cursorBenchmark 4.77us 209.61K
157 * skipBenchmark 4.78us 209.42K
158 * cloneBenchmark 26.65us 37.52K
159 * read 4.35us 230.07K
160 * readSlow 5.45us 183.48K
161 * prefixBaseline 6.44us 155.24K
162 * prefix 589.31% 1.09us 914.87K
163 * ============================================================================
166 int main(int argc, char** argv) {
167 gflags::ParseCommandLineFlags(&argc, &argv, true);
168 iobuf_benchmark = IOBuf::create(benchmark_size);
169 iobuf_benchmark->append(benchmark_size);
171 iobuf_read_benchmark = IOBuf::create(1);
172 for (int i = 0; i < benchmark_size; i++) {
173 unique_ptr<IOBuf> iobuf2(IOBuf::create(1));
175 iobuf_read_benchmark->prependChain(std::move(iobuf2));
178 folly::runBenchmarks();