Replace accumulation with blackhole.consume (#9275)
Motivation: SpotJMHBugs reports that accumulating a value as a way of eliding dead code elimination may be inadvisable, as discussed in `JMHSample_34_SafeLooping::measureWrong_2`. Change the test so that it consumes the response with `Blackhole::consume` instead. Modifications: - Replace addition of results with explicit `blackhole.consume()` call Result: Tests work as before, but with different benchmark numbers.
This commit is contained in:
parent
672fa0c779
commit
52169cba95
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017 The Netty Project
|
* Copyright 2019 The Netty Project
|
||||||
*
|
*
|
||||||
* The Netty Project licenses this file to you under the Apache License,
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
@ -22,6 +22,7 @@ import org.openjdk.jmh.annotations.OutputTimeUnit;
|
|||||||
import org.openjdk.jmh.annotations.Scope;
|
import org.openjdk.jmh.annotations.Scope;
|
||||||
import org.openjdk.jmh.annotations.State;
|
import org.openjdk.jmh.annotations.State;
|
||||||
import org.openjdk.jmh.annotations.Warmup;
|
import org.openjdk.jmh.annotations.Warmup;
|
||||||
|
import org.openjdk.jmh.infra.Blackhole;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -151,68 +152,56 @@ public class HttpMethodMapBenchmark extends AbstractMicrobenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
public int oldMapKnownMethods() throws Exception {
|
public void oldMapKnownMethods(Blackhole bh) throws Exception {
|
||||||
int x = 0;
|
|
||||||
for (int i = 0; i < KNOWN_METHODS.length; ++i) {
|
for (int i = 0; i < KNOWN_METHODS.length; ++i) {
|
||||||
x += OLD_MAP.get(KNOWN_METHODS[i]).toString().length();
|
bh.consume(OLD_MAP.get(KNOWN_METHODS[i]));
|
||||||
}
|
}
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
public int newMapKnownMethods() throws Exception {
|
public void newMapKnownMethods(Blackhole bh) throws Exception {
|
||||||
int x = 0;
|
|
||||||
for (int i = 0; i < KNOWN_METHODS.length; ++i) {
|
for (int i = 0; i < KNOWN_METHODS.length; ++i) {
|
||||||
x += NEW_MAP.get(KNOWN_METHODS[i]).toString().length();
|
bh.consume(NEW_MAP.get(KNOWN_METHODS[i]));
|
||||||
}
|
}
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
public int oldMapMixMethods() throws Exception {
|
public void oldMapMixMethods(Blackhole bh) throws Exception {
|
||||||
int x = 0;
|
|
||||||
for (int i = 0; i < MIXED_METHODS.length; ++i) {
|
for (int i = 0; i < MIXED_METHODS.length; ++i) {
|
||||||
HttpMethod method = OLD_MAP.get(MIXED_METHODS[i]);
|
HttpMethod method = OLD_MAP.get(MIXED_METHODS[i]);
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
x += method.toString().length();
|
bh.consume(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
public int newMapMixMethods() throws Exception {
|
public void newMapMixMethods(Blackhole bh) throws Exception {
|
||||||
int x = 0;
|
|
||||||
for (int i = 0; i < MIXED_METHODS.length; ++i) {
|
for (int i = 0; i < MIXED_METHODS.length; ++i) {
|
||||||
HttpMethod method = NEW_MAP.get(MIXED_METHODS[i]);
|
HttpMethod method = NEW_MAP.get(MIXED_METHODS[i]);
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
x += method.toString().length();
|
bh.consume(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
public int oldMapUnknownMethods() throws Exception {
|
public void oldMapUnknownMethods(Blackhole bh) throws Exception {
|
||||||
int x = 0;
|
|
||||||
for (int i = 0; i < UNKNOWN_METHODS.length; ++i) {
|
for (int i = 0; i < UNKNOWN_METHODS.length; ++i) {
|
||||||
HttpMethod method = OLD_MAP.get(UNKNOWN_METHODS[i]);
|
HttpMethod method = OLD_MAP.get(UNKNOWN_METHODS[i]);
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
x += method.toString().length();
|
bh.consume(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
public int newMapUnknownMethods() throws Exception {
|
public void newMapUnknownMethods(Blackhole bh) throws Exception {
|
||||||
int x = 0;
|
|
||||||
for (int i = 0; i < UNKNOWN_METHODS.length; ++i) {
|
for (int i = 0; i < UNKNOWN_METHODS.length; ++i) {
|
||||||
HttpMethod method = NEW_MAP.get(UNKNOWN_METHODS[i]);
|
HttpMethod method = NEW_MAP.get(UNKNOWN_METHODS[i]);
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
x += method.toString().length();
|
bh.consume(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import io.netty.util.concurrent.FastThreadLocal;
|
|||||||
import org.openjdk.jmh.annotations.Benchmark;
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
import org.openjdk.jmh.annotations.Measurement;
|
import org.openjdk.jmh.annotations.Measurement;
|
||||||
import org.openjdk.jmh.annotations.Threads;
|
import org.openjdk.jmh.annotations.Threads;
|
||||||
|
import org.openjdk.jmh.infra.Blackhole;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@ -56,20 +57,16 @@ public class FastThreadLocalFastPathBenchmark extends AbstractMicrobenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
public int jdkThreadLocalGet() {
|
public void jdkThreadLocalGet(Blackhole bh) {
|
||||||
int result = 0;
|
|
||||||
for (ThreadLocal<Integer> i: jdkThreadLocals) {
|
for (ThreadLocal<Integer> i: jdkThreadLocals) {
|
||||||
result += i.get();
|
bh.consume(i.get());
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
public int fastThreadLocal() {
|
public void fastThreadLocal(Blackhole bh) {
|
||||||
int result = 0;
|
|
||||||
for (FastThreadLocal<Integer> i: fastThreadLocals) {
|
for (FastThreadLocal<Integer> i: fastThreadLocals) {
|
||||||
result += i.get();
|
bh.consume(i.get());
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import io.netty.util.concurrent.FastThreadLocal;
|
|||||||
import org.openjdk.jmh.annotations.Benchmark;
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
import org.openjdk.jmh.annotations.Measurement;
|
import org.openjdk.jmh.annotations.Measurement;
|
||||||
import org.openjdk.jmh.annotations.Threads;
|
import org.openjdk.jmh.annotations.Threads;
|
||||||
|
import org.openjdk.jmh.infra.Blackhole;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@ -60,20 +61,16 @@ public class FastThreadLocalSlowPathBenchmark extends AbstractMicrobenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
public int jdkThreadLocalGet() {
|
public void jdkThreadLocalGet(Blackhole bh) {
|
||||||
int result = 0;
|
|
||||||
for (ThreadLocal<Integer> i: jdkThreadLocals) {
|
for (ThreadLocal<Integer> i: jdkThreadLocals) {
|
||||||
result += i.get();
|
bh.consume(i.get());
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
public int fastThreadLocal() {
|
public void fastThreadLocal(Blackhole bh) {
|
||||||
int result = 0;
|
|
||||||
for (FastThreadLocal<Integer> i: fastThreadLocals) {
|
for (FastThreadLocal<Integer> i: fastThreadLocals) {
|
||||||
result += i.get();
|
bh.consume(i.get());
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import org.openjdk.jmh.annotations.Setup;
|
|||||||
import org.openjdk.jmh.annotations.State;
|
import org.openjdk.jmh.annotations.State;
|
||||||
import org.openjdk.jmh.annotations.Threads;
|
import org.openjdk.jmh.annotations.Threads;
|
||||||
import org.openjdk.jmh.annotations.Warmup;
|
import org.openjdk.jmh.annotations.Warmup;
|
||||||
|
import org.openjdk.jmh.infra.Blackhole;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -68,23 +69,23 @@ public class ReadOnlyHttp2HeadersBenchmark extends AbstractMicrobenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
public int defaultTrailers() {
|
public void defaultTrailers(Blackhole bh) {
|
||||||
Http2Headers headers = new DefaultHttp2Headers(false);
|
Http2Headers headers = new DefaultHttp2Headers(false);
|
||||||
for (int i = 0; i < headerCount; ++i) {
|
for (int i = 0; i < headerCount; ++i) {
|
||||||
headers.add(headerNames[i], headerValues[i]);
|
headers.add(headerNames[i], headerValues[i]);
|
||||||
}
|
}
|
||||||
return iterate(headers);
|
iterate(headers, bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
public int readOnlyTrailers() {
|
public void readOnlyTrailers(Blackhole bh) {
|
||||||
return iterate(ReadOnlyHttp2Headers.trailers(false, buildPairs()));
|
iterate(ReadOnlyHttp2Headers.trailers(false, buildPairs()), bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
public int defaultClientHeaders() {
|
public void defaultClientHeaders(Blackhole bh) {
|
||||||
Http2Headers headers = new DefaultHttp2Headers(false);
|
Http2Headers headers = new DefaultHttp2Headers(false);
|
||||||
for (int i = 0; i < headerCount; ++i) {
|
for (int i = 0; i < headerCount; ++i) {
|
||||||
headers.add(headerNames[i], headerValues[i]);
|
headers.add(headerNames[i], headerValues[i]);
|
||||||
@ -93,39 +94,37 @@ public class ReadOnlyHttp2HeadersBenchmark extends AbstractMicrobenchmark {
|
|||||||
headers.scheme(HttpScheme.HTTPS.name());
|
headers.scheme(HttpScheme.HTTPS.name());
|
||||||
headers.path(path);
|
headers.path(path);
|
||||||
headers.authority(authority);
|
headers.authority(authority);
|
||||||
return iterate(headers);
|
iterate(headers, bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
public int readOnlyClientHeaders() {
|
public void readOnlyClientHeaders(Blackhole bh) {
|
||||||
return iterate(ReadOnlyHttp2Headers.clientHeaders(false, HttpMethod.POST.asciiName(), path,
|
iterate(ReadOnlyHttp2Headers.clientHeaders(false, HttpMethod.POST.asciiName(), path,
|
||||||
HttpScheme.HTTPS.name(), authority, buildPairs()));
|
HttpScheme.HTTPS.name(), authority, buildPairs()), bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
public int defaultServerHeaders() {
|
public void defaultServerHeaders(Blackhole bh) {
|
||||||
Http2Headers headers = new DefaultHttp2Headers(false);
|
Http2Headers headers = new DefaultHttp2Headers(false);
|
||||||
for (int i = 0; i < headerCount; ++i) {
|
for (int i = 0; i < headerCount; ++i) {
|
||||||
headers.add(headerNames[i], headerValues[i]);
|
headers.add(headerNames[i], headerValues[i]);
|
||||||
}
|
}
|
||||||
headers.status(HttpResponseStatus.OK.codeAsText());
|
headers.status(HttpResponseStatus.OK.codeAsText());
|
||||||
return iterate(headers);
|
iterate(headers, bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
public int readOnlyServerHeaders() {
|
public void readOnlyServerHeaders(Blackhole bh) {
|
||||||
return iterate(ReadOnlyHttp2Headers.serverHeaders(false, HttpResponseStatus.OK.codeAsText(), buildPairs()));
|
iterate(ReadOnlyHttp2Headers.serverHeaders(false, HttpResponseStatus.OK.codeAsText(), buildPairs()), bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int iterate(Http2Headers headers) {
|
private static void iterate(Http2Headers headers, Blackhole bh) {
|
||||||
int length = 0;
|
|
||||||
for (Map.Entry<CharSequence, CharSequence> entry : headers) {
|
for (Map.Entry<CharSequence, CharSequence> entry : headers) {
|
||||||
length += entry.getKey().length() + entry.getValue().length();
|
bh.consume(entry);
|
||||||
}
|
}
|
||||||
return length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AsciiString[] buildPairs() {
|
private AsciiString[] buildPairs() {
|
||||||
|
Loading…
Reference in New Issue
Block a user