1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.http;
17
18 import io.netty.microbench.util.AbstractMicrobenchmark;
19 import org.openjdk.jmh.annotations.Benchmark;
20 import org.openjdk.jmh.annotations.BenchmarkMode;
21 import org.openjdk.jmh.annotations.Level;
22 import org.openjdk.jmh.annotations.Measurement;
23 import org.openjdk.jmh.annotations.Mode;
24 import org.openjdk.jmh.annotations.OperationsPerInvocation;
25 import org.openjdk.jmh.annotations.OutputTimeUnit;
26 import org.openjdk.jmh.annotations.Setup;
27 import org.openjdk.jmh.annotations.Warmup;
28 import org.openjdk.jmh.infra.BenchmarkParams;
29 import org.openjdk.jmh.infra.Blackhole;
30 import org.openjdk.jmh.profile.LinuxPerfNormProfiler;
31 import org.openjdk.jmh.profile.ProfilerException;
32 import org.openjdk.jmh.profile.ProfilerFactory;
33 import org.openjdk.jmh.runner.options.ChainedOptionsBuilder;
34 import org.openjdk.jmh.runner.options.ProfilerConfig;
35
36 import java.text.DecimalFormat;
37 import java.util.SplittableRandom;
38 import java.util.concurrent.TimeUnit;
39
40 @BenchmarkMode(Mode.Throughput)
41 @Warmup(iterations = 10, time = 1)
42 @Measurement(iterations = 10, time = 1)
43 @OutputTimeUnit(TimeUnit.MICROSECONDS)
44 public class HttpStatusValueOfBenchmark extends AbstractMicrobenchmark {
45 private static final SplittableRandom random = new SplittableRandom();
46 private static final DecimalFormat df = new DecimalFormat("##.##%");
47 private static final int[] data_1300 = new int[1300];
48 private static final int[] data_2600 = new int[2600];
49 private static final int[] data_5300 = new int[5300];
50 private static final int[] data_11000 = new int[11000];
51 private static final int[] data_23000 = new int[23000];
52 private static final boolean ENABLE_POLLUTE = false;
53
54 @Setup(Level.Invocation)
55 public void setup(Blackhole bh, BenchmarkParams benchmarkParams) {
56 switch (benchmarkParams.getOpsPerInvocation()) {
57 case 1300 :
58 polluteBranchIfEnabled(bh, data_1300);
59 fillBenchMarkData(data_1300);
60 break;
61 case 2600 :
62 polluteBranchIfEnabled(bh, data_2600);
63 fillBenchMarkData(data_2600);
64 break;
65 case 5300 :
66 polluteBranchIfEnabled(bh, data_5300);
67 fillBenchMarkData(data_5300);
68 break;
69 case 11000 :
70 polluteBranchIfEnabled(bh, data_11000);
71 fillBenchMarkData(data_11000);
72 break;
73 case 23000 :
74 polluteBranchIfEnabled(bh, data_23000);
75 fillBenchMarkData(data_23000);
76 break;
77 }
78 }
79
80 @Benchmark
81 @OperationsPerInvocation(1300)
82 public void valueOf_1300(Blackhole bh) {
83 for (int code : data_1300) {
84 bh.consume(HttpStatusClass.valueOf(code));
85 }
86 }
87
88 @Benchmark
89 @OperationsPerInvocation(2600)
90 public void valueOf_2600(Blackhole bh) {
91 for (int code : data_2600) {
92 bh.consume(HttpStatusClass.valueOf(code));
93 }
94 }
95
96 @Benchmark
97 @OperationsPerInvocation(5300)
98 public void valueOf_5300(Blackhole bh) {
99 for (int code : data_5300) {
100 bh.consume(HttpStatusClass.valueOf(code));
101 }
102 }
103
104 @Benchmark
105 @OperationsPerInvocation(11000)
106 public void valueOf_11000(Blackhole bh) {
107 for (int code : data_11000) {
108 bh.consume(HttpStatusClass.valueOf(code));
109 }
110 }
111
112 @Benchmark
113 @OperationsPerInvocation(23000)
114 public void valueOf_23000(Blackhole bh) {
115 for (int code : data_23000) {
116 bh.consume(HttpStatusClass.valueOf(code));
117 }
118 }
119
120 public HttpStatusValueOfBenchmark() {
121
122 super(true);
123 }
124
125 private static void polluteBranchIfEnabled(Blackhole bh, int[] polluteData) {
126 if (ENABLE_POLLUTE) {
127 fillPolluteData(polluteData);
128 for (int code : polluteData) {
129 bh.consume(HttpStatusClass.valueOf(code));
130 }
131 }
132 }
133
134 private static void fillBenchMarkData(int[] benchMarkData) {
135 double c1x = 0, c2x = 0, c3x = 0, c4x = 0, c5x = 0, c6x = 0;
136 for (int i = 0; i < benchMarkData.length;) {
137
138 int code = random.nextInt(0, 100);
139
140 if (code < 38) {
141 benchMarkData[i++] = random.nextInt(100, 200);
142 ++c1x;
143 continue;
144 }
145
146 if (code < 68) {
147 benchMarkData[i++] = random.nextInt(200, 300);
148 ++c2x;
149 continue;
150 }
151
152 if (code < 83) {
153 benchMarkData[i++] = random.nextInt(300, 400);
154 ++c3x;
155 continue;
156 }
157
158 if (code < 93) {
159 benchMarkData[i++] = random.nextInt(400, 500);
160 ++c4x;
161 continue;
162 }
163
164 if (code < 98) {
165 benchMarkData[i++] = random.nextInt(500, 600);
166 ++c5x;
167 continue;
168 }
169
170 benchMarkData[i++] = random.nextInt(-50, 50);
171 ++c6x;
172 }
173
174 }
175
176 private static void fillPolluteData(int[] polluteData) {
177 double c1x = 0, c2x = 0, c3x = 0, c4x = 0, c5x = 0, c6x = 0;
178 for (int i = 0; i < polluteData.length;) {
179
180 int code = random.nextInt(0, 96);
181
182 if (code < 16) {
183 polluteData[i++] = random.nextInt(100, 200);
184 ++c1x;
185 continue;
186 }
187
188 if (code < 32) {
189 polluteData[i++] = random.nextInt(200, 300);
190 ++c2x;
191 continue;
192 }
193
194 if (code < 48) {
195 polluteData[i++] = random.nextInt(300, 400);
196 ++c3x;
197 continue;
198 }
199
200 if (code < 64) {
201 polluteData[i++] = random.nextInt(400, 500);
202 ++c4x;
203 continue;
204 }
205
206 if (code < 80) {
207 polluteData[i++] = random.nextInt(500, 600);
208 ++c5x;
209 continue;
210 }
211
212 polluteData[i++] = random.nextInt(-50, 50);
213 ++c6x;
214 }
215
216 }
217
218 @Override
219 protected ChainedOptionsBuilder newOptionsBuilder() throws Exception {
220 Class<LinuxPerfNormProfiler> profilerClass = LinuxPerfNormProfiler.class;
221 try {
222 ProfilerFactory.getProfilerOrException(new ProfilerConfig(profilerClass.getCanonicalName()));
223 } catch (ProfilerException t) {
224
225 return super.newOptionsBuilder();
226 }
227 return super.newOptionsBuilder().addProfiler(profilerClass);
228 }
229
230 private static void printCodePercentage(String desc, int length, double c1x, double c2x, double c3x, double c4x,
231 double c5x, double c6x) {
232 System.out.println("\n" + desc + "===>"
233 + "INFORMATIONAL:" + df.format(c1x / length)
234 + ", SUCCESS:" + df.format(c2x / length)
235 + ", REDIRECTION:" + df.format(c3x / length)
236 + ", CLIENT_ERROR:" + df.format(c4x / length)
237 + ", SERVER_ERROR:" + df.format(c5x / length)
238 + ", UNKNOWN:" + df.format(c6x / length)
239 );
240 }
241 }