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({ "true", "false" })
114 public String checkAccessible;
115
116 @Param({ "true", "false" })
117 public String checkBounds;
118
119 @Param({ "8" })
120 public int batchSize;
121
122 @Setup
123 public void setup() {
124 System.setProperty("io.netty.buffer.checkAccessible", checkAccessible);
125 System.setProperty("io.netty.buffer.checkBounds", checkBounds);
126 buffer = bufferType.newBuffer();
127 }
128
129 private ByteBuf buffer;
130
131 @TearDown
132 public void tearDown() {
133 buffer.release();
134 System.clearProperty("io.netty.buffer.checkAccessible");
135 System.clearProperty("io.netty.buffer.checkBounds");
136 }
137
138 @Benchmark
139 public long setGetLong() {
140 return buffer.setLong(0, 1).getLong(0);
141 }
142
143 @Benchmark
144 public ByteBuf setLong() {
145 return buffer.setLong(0, 1);
146 }
147
148 @Benchmark
149 public int readBatch() {
150 buffer.readerIndex(0).touch();
151 int result = 0;
152
153
154
155
156
157
158
159
160 for (int i = 0, size = batchSize; i < size; i++) {
161 result += buffer.readByte();
162 }
163 return result;
164 }
165 }