1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
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 <vector>
18
19 #include <folly/Benchmark.h>
20 #include <folly/io/Cursor.h>
21 #include <folly/io/IOBuf.h>
22 #include <folly/portability/GFlags.h>
23
24 using folly::IOBuf;
25 using std::unique_ptr;
26 using namespace std;
27
28 size_t buf_size = 0;
29 size_t num_bufs = 0;
30
BENCHMARK(reserveBenchmark,iters)31 BENCHMARK(reserveBenchmark, iters) {
32 while (iters--) {
33 unique_ptr<IOBuf> iobuf1(IOBuf::create(buf_size));
34 iobuf1->append(buf_size);
35 for (size_t bufs = num_bufs; bufs > 1; bufs--) {
36 iobuf1->reserve(0, buf_size);
37 iobuf1->append(buf_size);
38 }
39 }
40 }
41
BENCHMARK(chainBenchmark,iters)42 BENCHMARK(chainBenchmark, iters) {
43 while (iters--) {
44 unique_ptr<IOBuf> iobuf1(IOBuf::create(buf_size));
45 iobuf1->append(buf_size);
46 for (size_t bufs = num_bufs; bufs > 1; bufs--) {
47 unique_ptr<IOBuf> iobufNext(IOBuf::create(buf_size));
48 iobuf1->prependChain(std::move(iobufNext));
49 }
50 }
51 }
52
53 vector<unique_ptr<IOBuf>> bufPool;
poolGetIOBuf()54 inline unique_ptr<IOBuf> poolGetIOBuf() {
55 if (bufPool.size() > 0) {
56 unique_ptr<IOBuf> ret = std::move(bufPool.back());
57 bufPool.pop_back();
58 return ret;
59 } else {
60 unique_ptr<IOBuf> iobuf(IOBuf::create(buf_size));
61 iobuf->append(buf_size);
62 return iobuf;
63 }
64 }
65
poolPutIOBuf(unique_ptr<IOBuf> && buf)66 inline void poolPutIOBuf(unique_ptr<IOBuf>&& buf) {
67 unique_ptr<IOBuf> head = std::move(buf);
68 while (head) {
69 unique_ptr<IOBuf> next = head->pop();
70 bufPool.push_back(std::move(head));
71 head = std::move(next);
72 }
73 }
74
BENCHMARK(poolBenchmark,iters)75 BENCHMARK(poolBenchmark, iters) {
76 while (iters--) {
77 unique_ptr<IOBuf> head = poolGetIOBuf();
78 for (size_t bufs = num_bufs; bufs > 1; bufs--) {
79 unique_ptr<IOBuf> iobufNext = poolGetIOBuf();
80 head->prependChain(std::move(iobufNext));
81 }
82 // cleanup
83 poolPutIOBuf(std::move(head));
84 }
85 }
86
setNumbers(size_t size,size_t num)87 void setNumbers(size_t size, size_t num) {
88 buf_size = size;
89 num_bufs = num;
90 bufPool.clear();
91
92 printf("\nBuffer size: %zu, number of buffers: %zu\n\n", size, num);
93 }
94
95 /*
96 ------------------------------------------------------------------------------
97 reserveBenchmark 100000 9.186 ms 91.86 ns 10.38 M
98 chainBenchmark 100000 59.44 ms 594.4 ns 1.604 M
99 poolBenchmark 100000 15.87 ms 158.7 ns 6.01 M
100
101 Buffer size: 100, number of buffers: 10
102
103 Benchmark Iters Total t t/iter iter/sec
104 ------------------------------------------------------------------------------
105 reserveBenchmark 100000 62 ms 620 ns 1.538 M
106 chainBenchmark 100000 59.48 ms 594.8 ns 1.603 M
107 poolBenchmark 100000 16.07 ms 160.7 ns 5.933 M
108
109 Buffer size: 2048, number of buffers: 10
110
111 Benchmark Iters Total t t/iter iter/sec
112 ------------------------------------------------------------------------------
113 reserveBenchmark 100000 148.4 ms 1.484 us 658.2 k
114 chainBenchmark 100000 140.9 ms 1.409 us 693 k
115 poolBenchmark 100000 16.73 ms 167.3 ns 5.7 M
116
117 Buffer size: 10000, number of buffers: 10
118
119 Benchmark Iters Total t t/iter iter/sec
120 ------------------------------------------------------------------------------
121 reserveBenchmark 100000 234 ms 2.34 us 417.3 k
122 chainBenchmark 100000 142.3 ms 1.423 us 686.1 k
123 poolBenchmark 100000 16.78 ms 167.8 ns 5.684 M
124
125 Buffer size: 100000, number of buffers: 10
126
127 Benchmark Iters Total t t/iter iter/sec
128 ------------------------------------------------------------------------------
129 reserveBenchmark 100000 186.5 ms 1.865 us 523.5 k
130 chainBenchmark 100000 360.5 ms 3.605 us 270.9 k
131 poolBenchmark 100000 16.52 ms 165.2 ns 5.772 M
132
133 Buffer size: 1000000, number of buffers: 10
134
135 Benchmark Iters Total t t/iter iter/sec
136 ------------------------------------------------------------------------------
137 reserveBenchmark 156 2.084 s 13.36 ms 74.84
138 chainBenchmark 30082 2.001 s 66.5 us 14.68 k
139 poolBenchmark 100000 18.18 ms 181.8 ns 5.244 M
140
141
142 Buffer size: 10, number of buffers: 20
143
144 Benchmark Iters Total t t/iter iter/sec
145 ------------------------------------------------------------------------------
146 reserveBenchmark 100000 12.54 ms 125.4 ns 7.603 M
147 chainBenchmark 100000 118.6 ms 1.186 us 823.2 k
148 poolBenchmark 100000 32.2 ms 322 ns 2.962 M
149 */
main(int argc,char ** argv)150 int main(int argc, char** argv) {
151 gflags::ParseCommandLineFlags(&argc, &argv, true);
152
153 setNumbers(10, 10);
154 folly::runBenchmarks();
155 setNumbers(100, 10);
156 folly::runBenchmarks();
157 setNumbers(2048, 10);
158 folly::runBenchmarks();
159 setNumbers(10000, 10);
160 folly::runBenchmarks();
161 setNumbers(100000, 10);
162 folly::runBenchmarks();
163 setNumbers(1000000, 10);
164 folly::runBenchmarks();
165
166 setNumbers(10, 20);
167 folly::runBenchmarks();
168
169 return 0;
170 }
171