HTTP/2 Frame Writer Microbenchmark Fix
Motivation: The Http2FrameWriterBenchmark JMH harness class name was not updated for the JVM arguments. The number of forks is 0 which means the JHM will share a JVM with the benchmarks. Sharing the JVM may lead to less reliable benchmarking results and as doesn't allow for the command line arguments to be applied for each benchmark. Modifications: - Update the JMH version from 0.9 to 1.7.1. Benchmarks wouldn't run on old version. - Increase the number of forks from 0 to 1. - Remove allocation of environment from static and cleanup AfterClass to using the Setup and Teardown methods. The forked JVM would not shut down correctly otherwise (and wait for 30+ seconds before timeing out). Result: Benchmarks that run as intended.
This commit is contained in:
parent
9c4af6af7e
commit
d556269810
@ -73,12 +73,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openjdk.jmh</groupId>
|
<groupId>org.openjdk.jmh</groupId>
|
||||||
<artifactId>jmh-core</artifactId>
|
<artifactId>jmh-core</artifactId>
|
||||||
<version>0.9</version>
|
<version>1.7.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openjdk.jmh</groupId>
|
<groupId>org.openjdk.jmh</groupId>
|
||||||
<artifactId>jmh-generator-annprocess</artifactId>
|
<artifactId>jmh-generator-annprocess</artifactId>
|
||||||
<version>0.9</version>
|
<version>1.7.1</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -34,7 +34,6 @@ import io.netty.channel.ChannelPipeline;
|
|||||||
import io.netty.channel.EventLoop;
|
import io.netty.channel.EventLoop;
|
||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
import io.netty.channel.ServerChannel;
|
import io.netty.channel.ServerChannel;
|
||||||
import io.netty.channel.epoll.Epoll;
|
|
||||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||||
import io.netty.channel.epoll.EpollServerSocketChannel;
|
import io.netty.channel.epoll.EpollServerSocketChannel;
|
||||||
import io.netty.channel.epoll.EpollSocketChannel;
|
import io.netty.channel.epoll.EpollSocketChannel;
|
||||||
@ -66,17 +65,15 @@ import io.netty.util.concurrent.Future;
|
|||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.openjdk.jmh.annotations.Benchmark;
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
import org.openjdk.jmh.annotations.Level;
|
import org.openjdk.jmh.annotations.Level;
|
||||||
import org.openjdk.jmh.annotations.Param;
|
import org.openjdk.jmh.annotations.Param;
|
||||||
import org.openjdk.jmh.annotations.Scope;
|
import org.openjdk.jmh.annotations.Scope;
|
||||||
import org.openjdk.jmh.annotations.Setup;
|
import org.openjdk.jmh.annotations.Setup;
|
||||||
import org.openjdk.jmh.annotations.State;
|
import org.openjdk.jmh.annotations.State;
|
||||||
|
import org.openjdk.jmh.annotations.TearDown;
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchmark {
|
public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchmark {
|
||||||
@ -94,37 +91,26 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
|
|||||||
new OioEnvironmentParametersBase(PooledByteBufAllocator.DEFAULT);
|
new OioEnvironmentParametersBase(PooledByteBufAllocator.DEFAULT);
|
||||||
|
|
||||||
public static enum EnvironmentType {
|
public static enum EnvironmentType {
|
||||||
EMBEDDED_POOLED, EMBEDDED_UNPOOLED,
|
EMBEDDED_POOLED(NIO_POOLED_PARAMS), EMBEDDED_UNPOOLED(NIO_UNPOOLED_PARAMS),
|
||||||
NIO_POOLED, NIO_UNPOOLED,
|
NIO_POOLED(NIO_POOLED_PARAMS), NIO_UNPOOLED(NIO_UNPOOLED_PARAMS),
|
||||||
EPOLL_POOLED, EPOLL_UNPOOLED,
|
EPOLL_POOLED(EPOLL_POOLED_PARAMS), EPOLL_UNPOOLED(EPOLL_UNPOOLED_PARAMS),
|
||||||
OIO_POOLED, OIO_UNPOOLED;
|
OIO_POOLED(OIO_POOLED_PARAMS), OIO_UNPOOLED(OIO_UNPOOLED_PARAMS);
|
||||||
|
|
||||||
|
private final EnvironmentParameters params;
|
||||||
|
|
||||||
|
private EnvironmentType(EnvironmentParameters params) {
|
||||||
|
this.params = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnvironmentParameters params() {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum DataPayloadType {
|
public static enum DataPayloadType {
|
||||||
SMALL, MEDIUM, LARGE, JUMBO;
|
SMALL, MEDIUM, LARGE, JUMBO;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Map<EnvironmentType, Environment> ENVIRONMENTS = new HashMap<EnvironmentType, Environment>();
|
|
||||||
private static final Map<DataPayloadType, BenchmarkTestPayload> PAYLOADS =
|
|
||||||
new HashMap<DataPayloadType, BenchmarkTestPayload>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
ENVIRONMENTS.put(EnvironmentType.OIO_POOLED, boostrapEnvWithTransport(OIO_POOLED_PARAMS));
|
|
||||||
ENVIRONMENTS.put(EnvironmentType.OIO_UNPOOLED, boostrapEnvWithTransport(OIO_UNPOOLED_PARAMS));
|
|
||||||
ENVIRONMENTS.put(EnvironmentType.NIO_POOLED, boostrapEnvWithTransport(NIO_POOLED_PARAMS));
|
|
||||||
ENVIRONMENTS.put(EnvironmentType.NIO_UNPOOLED, boostrapEnvWithTransport(NIO_UNPOOLED_PARAMS));
|
|
||||||
if (Epoll.isAvailable()) {
|
|
||||||
ENVIRONMENTS.put(EnvironmentType.EPOLL_POOLED, boostrapEnvWithTransport(EPOLL_POOLED_PARAMS));
|
|
||||||
ENVIRONMENTS.put(EnvironmentType.EPOLL_UNPOOLED, boostrapEnvWithTransport(EPOLL_UNPOOLED_PARAMS));
|
|
||||||
}
|
|
||||||
ENVIRONMENTS.put(EnvironmentType.EMBEDDED_POOLED, boostrapEmbeddedEnv(PooledByteBufAllocator.DEFAULT));
|
|
||||||
ENVIRONMENTS.put(EnvironmentType.EMBEDDED_UNPOOLED, boostrapEmbeddedEnv(UnpooledByteBufAllocator.DEFAULT));
|
|
||||||
PAYLOADS.put(DataPayloadType.SMALL, createPayload(DataPayloadType.SMALL));
|
|
||||||
PAYLOADS.put(DataPayloadType.MEDIUM, createPayload(DataPayloadType.MEDIUM));
|
|
||||||
PAYLOADS.put(DataPayloadType.LARGE, createPayload(DataPayloadType.LARGE));
|
|
||||||
PAYLOADS.put(DataPayloadType.JUMBO, createPayload(DataPayloadType.JUMBO));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Param
|
@Param
|
||||||
public EnvironmentType environmentType;
|
public EnvironmentType environmentType;
|
||||||
|
|
||||||
@ -138,28 +124,31 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
|
|||||||
|
|
||||||
private BenchmarkTestPayload payload;
|
private BenchmarkTestPayload payload;
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void teardown() {
|
|
||||||
for (Environment env : ENVIRONMENTS.values()) {
|
|
||||||
try {
|
|
||||||
env.teardown();
|
|
||||||
} catch (Exception e) {
|
|
||||||
handleUnexpectedException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (BenchmarkTestPayload payload : PAYLOADS.values()) {
|
|
||||||
payload.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Setup(Level.Trial)
|
@Setup(Level.Trial)
|
||||||
public void setup() {
|
public void setup() {
|
||||||
environment = ENVIRONMENTS.get(environmentType);
|
switch (environmentType) {
|
||||||
|
case EMBEDDED_POOLED:
|
||||||
|
case EMBEDDED_UNPOOLED:
|
||||||
|
environment = boostrapEmbeddedEnv(environmentType);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
environment = boostrapEnvWithTransport(environmentType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (environment == null) {
|
if (environment == null) {
|
||||||
throw new IllegalStateException("Environment type [" + environmentType + "] is not supported.");
|
throw new IllegalStateException("Environment type [" + environmentType + "] is not supported.");
|
||||||
}
|
}
|
||||||
AbstractSharedExecutorMicrobenchmark.executor(environment.eventLoop());
|
AbstractSharedExecutorMicrobenchmark.executor(environment.eventLoop());
|
||||||
payload = PAYLOADS.get(dataType);
|
payload = createPayload(dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TearDown(Level.Trial)
|
||||||
|
public void teardown() throws Exception {
|
||||||
|
try {
|
||||||
|
environment.teardown();
|
||||||
|
} finally {
|
||||||
|
payload.release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@ -233,7 +222,8 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Environment boostrapEnvWithTransport(final EnvironmentParameters params) {
|
private static Environment boostrapEnvWithTransport(final EnvironmentType environmentType) {
|
||||||
|
final EnvironmentParameters params = environmentType.params();
|
||||||
ServerBootstrap sb = new ServerBootstrap();
|
ServerBootstrap sb = new ServerBootstrap();
|
||||||
Bootstrap cb = new Bootstrap();
|
Bootstrap cb = new Bootstrap();
|
||||||
final TrasportEnvironment environment = new TrasportEnvironment(cb, sb);
|
final TrasportEnvironment environment = new TrasportEnvironment(cb, sb);
|
||||||
@ -282,7 +272,8 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
|
|||||||
return environment;
|
return environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Environment boostrapEmbeddedEnv(final ByteBufAllocator alloc) {
|
private static Environment boostrapEmbeddedEnv(final EnvironmentType environmentType) {
|
||||||
|
final ByteBufAllocator alloc = environmentType.params().clientAllocator();
|
||||||
final EmbeddedEnvironment env = new EmbeddedEnvironment(new DefaultHttp2FrameWriter());
|
final EmbeddedEnvironment env = new EmbeddedEnvironment(new DefaultHttp2FrameWriter());
|
||||||
final Http2Connection connection = new DefaultHttp2Connection(false);
|
final Http2Connection connection = new DefaultHttp2Connection(false);
|
||||||
Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(connection, env.writer());
|
Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(connection, env.writer());
|
||||||
|
@ -42,7 +42,7 @@ public abstract class AbstractMicrobenchmarkBase {
|
|||||||
protected static final int DEFAULT_MEASURE_ITERATIONS = 10;
|
protected static final int DEFAULT_MEASURE_ITERATIONS = 10;
|
||||||
protected static final String[] BASE_JVM_ARGS = {
|
protected static final String[] BASE_JVM_ARGS = {
|
||||||
"-server", "-dsa", "-da", "-ea:io.netty...", "-XX:+AggressiveOpts", "-XX:+UseBiasedLocking",
|
"-server", "-dsa", "-da", "-ea:io.netty...", "-XX:+AggressiveOpts", "-XX:+UseBiasedLocking",
|
||||||
"-XX:+UseFastAccessorMethods", "-XX:+UseStringCache", "-XX:+OptimizeStringConcat",
|
"-XX:+UseFastAccessorMethods", "-XX:+OptimizeStringConcat",
|
||||||
"-XX:+HeapDumpOnOutOfMemoryError", "-Dio.netty.noResourceLeakDetection"};
|
"-XX:+HeapDumpOnOutOfMemoryError", "-Dio.netty.noResourceLeakDetection"};
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -33,13 +33,13 @@ import org.openjdk.jmh.annotations.Fork;
|
|||||||
@Fork(AbstractSharedExecutorMicrobenchmark.DEFAULT_FORKS)
|
@Fork(AbstractSharedExecutorMicrobenchmark.DEFAULT_FORKS)
|
||||||
public class AbstractSharedExecutorMicrobenchmark extends AbstractMicrobenchmarkBase {
|
public class AbstractSharedExecutorMicrobenchmark extends AbstractMicrobenchmarkBase {
|
||||||
|
|
||||||
protected static final int DEFAULT_FORKS = 0; // Forks has to be 0 so tasks are run immediately by JMH
|
protected static final int DEFAULT_FORKS = 1;
|
||||||
protected static final String[] JVM_ARGS;
|
protected static final String[] JVM_ARGS;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
final String[] customArgs = {
|
final String[] customArgs = {
|
||||||
"-Xms2g", "-Xmx2g", "-XX:MaxDirectMemorySize=2g", "-Dharness.executor=CUSTOM",
|
"-Xms2g", "-Xmx2g", "-XX:MaxDirectMemorySize=2g", "-Dharness.executor=CUSTOM",
|
||||||
"-Dharness.executor.class=io.netty.microbench.util.AbstractExecutorMicrobenchmark$DelegateHarnessExecutor" };
|
"-Dharness.executor.class=io.netty.microbench.util.AbstractSharedExecutorMicrobenchmark$DelegateHarnessExecutor" };
|
||||||
|
|
||||||
JVM_ARGS = new String[BASE_JVM_ARGS.length + customArgs.length];
|
JVM_ARGS = new String[BASE_JVM_ARGS.length + customArgs.length];
|
||||||
System.arraycopy(BASE_JVM_ARGS, 0, JVM_ARGS, 0, BASE_JVM_ARGS.length);
|
System.arraycopy(BASE_JVM_ARGS, 0, JVM_ARGS, 0, BASE_JVM_ARGS.length);
|
||||||
|
Loading…
Reference in New Issue
Block a user