View Javadoc
1   /*
2    * Copyright 2018 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://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, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.buffer;
17  
18  import io.netty.microbench.util.AbstractMicrobenchmark;
19  import io.netty.util.ByteProcessor;
20  
21  import org.openjdk.jmh.annotations.Benchmark;
22  import org.openjdk.jmh.annotations.Measurement;
23  import org.openjdk.jmh.annotations.Param;
24  import org.openjdk.jmh.annotations.Setup;
25  import org.openjdk.jmh.annotations.TearDown;
26  import org.openjdk.jmh.annotations.Warmup;
27  
28  import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
29  import static io.netty.buffer.Unpooled.wrappedBuffer;
30  
31  import java.util.ArrayList;
32  import java.util.List;
33  import java.util.concurrent.TimeUnit;
34  
35  @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
36  @Measurement(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS)
37  public class CompositeByteBufSequentialBenchmark extends AbstractMicrobenchmark {
38  
39      public enum ByteBufType {
40          SMALL_CHUNKS {
41              @Override
42              ByteBuf newBuffer(int length) {
43                  return newBufferSmallChunks(length);
44              }
45          },
46          LARGE_CHUNKS {
47              @Override
48              ByteBuf newBuffer(int length) {
49                  return newBufferLargeChunks(length);
50              }
51          };
52          abstract ByteBuf newBuffer(int length);
53      }
54  
55      @Param({
56              "8",
57              "64",
58              "1024",
59              "10240",
60              "102400",
61              "1024000",
62      })
63      public int size;
64  
65      @Param
66      public ByteBufType bufferType;
67  
68      private ByteBuf buffer;
69  
70      @Setup
71      public void setup() {
72          buffer = bufferType.newBuffer(size);
73      }
74  
75      @TearDown
76      public void teardown() {
77          buffer.release();
78      }
79  
80      private static final ByteProcessor TEST_PROCESSOR = new ByteProcessor() {
81          @Override
82          public boolean process(byte value) throws Exception {
83              return value == 'b'; // false
84          }
85      };
86  
87      @Benchmark
88      public int forEachByte() {
89          buffer.setIndex(0, buffer.capacity());
90          buffer.forEachByte(TEST_PROCESSOR);
91          return buffer.forEachByteDesc(TEST_PROCESSOR);
92      }
93  
94      @Benchmark
95      public int sequentialWriteAndRead() {
96          buffer.clear();
97          for (int i = 0, l = buffer.writableBytes(); i < l; i++) {
98              buffer.writeByte('a');
99          }
100         for (int i = 0, l = buffer.readableBytes(); i < l; i++) {
101             if (buffer.readByte() == 'b') {
102                 return -1;
103             }
104         }
105         return 1;
106     }
107 
108     private static ByteBuf newBufferSmallChunks(int length) {
109 
110         List<ByteBuf> buffers = new ArrayList<ByteBuf>(((length + 1) / 45) * 19);
111         for (int i = 0; i < length + 45; i += 45) {
112             for (int j = 1; j <= 9; j++) {
113                 buffers.add(EMPTY_BUFFER);
114                 buffers.add(wrappedBuffer(new byte[j]));
115             }
116             buffers.add(EMPTY_BUFFER);
117         }
118 
119         ByteBuf buffer = wrappedBuffer(Integer.MAX_VALUE, buffers.toArray(new ByteBuf[0]));
120 
121         // Truncate to the requested capacity.
122         return buffer.capacity(length).writerIndex(0);
123     }
124 
125     private static ByteBuf newBufferLargeChunks(int length) {
126 
127         List<ByteBuf> buffers = new ArrayList<ByteBuf>((length + 1) / 512);
128         for (int i = 0; i < length + 1536; i += 1536) {
129             buffers.add(wrappedBuffer(new byte[512]));
130             buffers.add(EMPTY_BUFFER);
131             buffers.add(wrappedBuffer(new byte[1024]));
132         }
133 
134         ByteBuf buffer = wrappedBuffer(Integer.MAX_VALUE, buffers.toArray(new ByteBuf[0]));
135 
136         // Truncate to the requested capacity.
137         return buffer.capacity(length).writerIndex(0);
138     }
139 }