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({ "8", "64", "1024", "10240", "102400", "1024000" })
56      public int size;
57  
58      @Param
59      public ByteBufType bufferType;
60  
61      private ByteBuf buffer;
62  
63      @Setup
64      public void setup() {
65          buffer = bufferType.newBuffer(size);
66      }
67  
68      @TearDown
69      public void teardown() {
70          buffer.release();
71      }
72  
73      private static final ByteProcessor TEST_PROCESSOR = new ByteProcessor() {
74          @Override
75          public boolean process(byte value) throws Exception {
76              return value == 'b'; // false
77          }
78      };
79  
80      @Benchmark
81      public int forEachByte() {
82          buffer.setIndex(0, buffer.capacity());
83          buffer.forEachByte(TEST_PROCESSOR);
84          return buffer.forEachByteDesc(TEST_PROCESSOR);
85      }
86  
87      @Benchmark
88      public int sequentialWriteAndRead() {
89          buffer.clear();
90          for (int i = 0, l = buffer.writableBytes(); i < l; i++) {
91              buffer.writeByte('a');
92          }
93          for (int i = 0, l = buffer.readableBytes(); i < l; i++) {
94              if (buffer.readByte() == 'b') {
95                  return -1;
96              }
97          }
98          return 1;
99      }
100 
101     private static ByteBuf newBufferSmallChunks(int length) {
102 
103         List<ByteBuf> buffers = new ArrayList<ByteBuf>(((length + 1) / 45) * 19);
104         for (int i = 0; i < length + 45; i += 45) {
105             for (int j = 1; j <= 9; j++) {
106                 buffers.add(EMPTY_BUFFER);
107                 buffers.add(wrappedBuffer(new byte[j]));
108             }
109             buffers.add(EMPTY_BUFFER);
110         }
111 
112         ByteBuf buffer = wrappedBuffer(Integer.MAX_VALUE, buffers.toArray(new ByteBuf[0]));
113 
114         // Truncate to the requested capacity.
115         return buffer.capacity(length).writerIndex(0);
116     }
117 
118     private static ByteBuf newBufferLargeChunks(int length) {
119 
120         List<ByteBuf> buffers = new ArrayList<ByteBuf>((length + 1) / 512);
121         for (int i = 0; i < length + 1536; i += 1536) {
122             buffers.add(wrappedBuffer(new byte[512]));
123             buffers.add(EMPTY_BUFFER);
124             buffers.add(wrappedBuffer(new byte[1024]));
125         }
126 
127         ByteBuf buffer = wrappedBuffer(Integer.MAX_VALUE, buffers.toArray(new ByteBuf[0]));
128 
129         // Truncate to the requested capacity.
130         return buffer.capacity(length).writerIndex(0);
131     }
132 }