1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.http2;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.Unpooled;
20 import io.netty.microbench.util.AbstractMicrobenchmark;
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.Scope;
28 import org.openjdk.jmh.annotations.Setup;
29 import org.openjdk.jmh.annotations.State;
30 import org.openjdk.jmh.annotations.Threads;
31 import org.openjdk.jmh.annotations.Warmup;
32
33 import java.util.concurrent.TimeUnit;
34
35 @Threads(1)
36 @State(Scope.Benchmark)
37 @Fork(1)
38 @Warmup(iterations = 5)
39 @Measurement(iterations = 10)
40 @OutputTimeUnit(TimeUnit.NANOSECONDS)
41 public class HpackDecoderULE128Benchmark extends AbstractMicrobenchmark {
42 private static final Http2Exception DECODE_ULE_128_TO_LONG_DECOMPRESSION_EXCEPTION =
43 new Http2Exception(Http2Error.COMPRESSION_ERROR);
44 private static final Http2Exception DECODE_ULE_128_TO_INT_DECOMPRESSION_EXCEPTION =
45 new Http2Exception(Http2Error.COMPRESSION_ERROR);
46 private static final Http2Exception DECODE_ULE_128_DECOMPRESSION_EXCEPTION =
47 new Http2Exception(Http2Error.COMPRESSION_ERROR);
48
49 private ByteBuf longMaxBuf;
50 private ByteBuf intMaxBuf;
51
52 @Setup
53 public void setup() {
54 byte[] longMax = {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
55 (byte) 0xFF, (byte) 0x7F};
56 longMaxBuf = Unpooled.wrappedBuffer(longMax);
57 byte[] intMax = {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x07};
58 intMaxBuf = Unpooled.wrappedBuffer(intMax);
59 }
60
61 @Benchmark
62 @BenchmarkMode(Mode.AverageTime)
63 public long decodeMaxLong() throws Http2Exception {
64 long v = decodeULE128(longMaxBuf, 0L);
65 longMaxBuf.readerIndex(0);
66 return v;
67 }
68
69 @Benchmark
70 @BenchmarkMode(Mode.AverageTime)
71 public long decodeMaxIntWithLong() throws Http2Exception {
72 long v = decodeULE128(intMaxBuf, 0L);
73 intMaxBuf.readerIndex(0);
74 return v;
75 }
76
77 @Benchmark
78 @BenchmarkMode(Mode.AverageTime)
79 public int decodeMaxInt() throws Http2Exception {
80 int v = decodeULE128(intMaxBuf, 0);
81 intMaxBuf.readerIndex(0);
82 return v;
83 }
84
85 @Benchmark
86 @BenchmarkMode(Mode.AverageTime)
87 public int decodeMaxIntUsingLong() throws Http2Exception {
88 int v = decodeULE128UsingLong(intMaxBuf, 0);
89 intMaxBuf.readerIndex(0);
90 return v;
91 }
92
93 static int decodeULE128UsingLong(ByteBuf in, int result) throws Http2Exception {
94 final int readerIndex = in.readerIndex();
95 final long v = decodeULE128(in, (long) result);
96 if (v > Integer.MAX_VALUE) {
97 in.readerIndex(readerIndex);
98 throw DECODE_ULE_128_TO_INT_DECOMPRESSION_EXCEPTION;
99 }
100 return (int) v;
101 }
102
103 static long decodeULE128(ByteBuf in, long result) throws Http2Exception {
104 assert result <= 0x7f && result >= 0;
105 final boolean resultStartedAtZero = result == 0;
106 final int writerIndex = in.writerIndex();
107 for (int readerIndex = in.readerIndex(), shift = 0; readerIndex < writerIndex; ++readerIndex, shift += 7) {
108 byte b = in.getByte(readerIndex);
109 if (shift == 56 && ((b & 0x80) != 0 || b == 0x7F && !resultStartedAtZero)) {
110
111
112
113
114
115
116
117 throw DECODE_ULE_128_TO_LONG_DECOMPRESSION_EXCEPTION;
118 }
119
120 if ((b & 0x80) == 0) {
121 in.readerIndex(readerIndex + 1);
122 return result + ((b & 0x7FL) << shift);
123 }
124 result += (b & 0x7FL) << shift;
125 }
126
127 throw DECODE_ULE_128_DECOMPRESSION_EXCEPTION;
128 }
129
130 static int decodeULE128(ByteBuf in, int result) throws Http2Exception {
131 assert result <= 0x7f && result >= 0;
132 final boolean resultStartedAtZero = result == 0;
133 final int writerIndex = in.writerIndex();
134 for (int readerIndex = in.readerIndex(), shift = 0; readerIndex < writerIndex; ++readerIndex, shift += 7) {
135 byte b = in.getByte(readerIndex);
136 if (shift == 28 && ((b & 0x80) != 0 || !resultStartedAtZero && b > 6 || resultStartedAtZero && b > 7)) {
137
138
139
140
141
142 throw DECODE_ULE_128_TO_INT_DECOMPRESSION_EXCEPTION;
143 }
144
145 if ((b & 0x80) == 0) {
146 in.readerIndex(readerIndex + 1);
147 return result + ((b & 0x7F) << shift);
148 }
149 result += (b & 0x7F) << shift;
150 }
151
152 throw DECODE_ULE_128_DECOMPRESSION_EXCEPTION;
153 }
154 }