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