1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.buffer;
17
18 import java.nio.ByteBuffer;
19 import java.util.concurrent.TimeUnit;
20
21 import org.openjdk.jmh.annotations.Benchmark;
22 import org.openjdk.jmh.annotations.BenchmarkMode;
23 import org.openjdk.jmh.annotations.Fork;
24 import org.openjdk.jmh.annotations.Measurement;
25 import org.openjdk.jmh.annotations.Mode;
26 import org.openjdk.jmh.annotations.OutputTimeUnit;
27 import org.openjdk.jmh.annotations.Param;
28 import org.openjdk.jmh.annotations.Setup;
29 import org.openjdk.jmh.annotations.TearDown;
30 import org.openjdk.jmh.annotations.Warmup;
31
32 import io.netty.microbench.util.AbstractMicrobenchmark;
33 import io.netty.util.internal.PlatformDependent;
34
35 @Warmup(iterations = 5, time = 1500, timeUnit = TimeUnit.MILLISECONDS)
36 @Measurement(iterations = 10, time = 1500, timeUnit = TimeUnit.MILLISECONDS)
37 @Fork(3)
38 @BenchmarkMode(Mode.AverageTime)
39 @OutputTimeUnit(TimeUnit.NANOSECONDS)
40 public class ByteBufAccessBenchmark extends AbstractMicrobenchmark {
41
42 static final class NioFacade extends WrappedByteBuf {
43 private final ByteBuffer byteBuffer;
44 NioFacade(ByteBuffer byteBuffer) {
45 super(Unpooled.EMPTY_BUFFER);
46 this.byteBuffer = byteBuffer;
47 }
48 @Override
49 public ByteBuf setLong(int index, long value) {
50 byteBuffer.putLong(index, value);
51 return this;
52 }
53 @Override
54 public long getLong(int index) {
55 return byteBuffer.getLong(index);
56 }
57 @Override
58 public byte readByte() {
59 return byteBuffer.get();
60 }
61 @Override
62 public ByteBuf touch() {
63
64 byteBuffer.position(0);
65 return this;
66 }
67 @Override
68 public boolean release() {
69 PlatformDependent.freeDirectBuffer(byteBuffer);
70 return true;
71 }
72 }
73
74 public enum ByteBufType {
75 UNSAFE {
76 @Override
77 ByteBuf newBuffer() {
78 return new UnpooledUnsafeDirectByteBuf(
79 UnpooledByteBufAllocator.DEFAULT, 64, 64).setIndex(0, 64);
80 }
81 },
82 UNSAFE_SLICE {
83 @Override
84 ByteBuf newBuffer() {
85 return UNSAFE.newBuffer().slice(16, 48);
86 }
87 },
88 HEAP {
89 @Override
90 ByteBuf newBuffer() {
91 return new UnpooledUnsafeHeapByteBuf(
92 UnpooledByteBufAllocator.DEFAULT, 64, 64).setIndex(0, 64);
93 }
94 },
95 COMPOSITE {
96 @Override
97 ByteBuf newBuffer() {
98 return Unpooled.wrappedBuffer(UNSAFE.newBuffer(), HEAP.newBuffer());
99 }
100 },
101 NIO {
102 @Override
103 ByteBuf newBuffer() {
104 return new NioFacade(ByteBuffer.allocateDirect(64));
105 }
106 };
107 abstract ByteBuf newBuffer();
108 }
109
110 @Param
111 public ByteBufType bufferType;
112
113 @Param({
114 "true",
115 "false",
116 })
117 public String checkAccessible;
118
119 @Param({
120 "true",
121 "false",
122 })
123 public String checkBounds;
124
125 @Param({
126 "8",
127 })
128 public int batchSize;
129
130 @Setup
131 public void setup() {
132 System.setProperty("io.netty.buffer.checkAccessible", checkAccessible);
133 System.setProperty("io.netty.buffer.checkBounds", checkBounds);
134 buffer = bufferType.newBuffer();
135 }
136
137 private ByteBuf buffer;
138
139 @TearDown
140 public void tearDown() {
141 buffer.release();
142 System.clearProperty("io.netty.buffer.checkAccessible");
143 System.clearProperty("io.netty.buffer.checkBounds");
144 }
145
146 @Benchmark
147 public long setGetLong() {
148 return buffer.setLong(0, 1).getLong(0);
149 }
150
151 @Benchmark
152 public ByteBuf setLong() {
153 return buffer.setLong(0, 1);
154 }
155
156 @Benchmark
157 public int readBatch() {
158 buffer.readerIndex(0).touch();
159 int result = 0;
160
161
162
163
164
165
166
167
168 for (int i = 0, size = batchSize; i < size; i++) {
169 result += buffer.readByte();
170 }
171 return result;
172 }
173 }