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:
Scott Mitchell 2015-04-11 09:47:51 -07:00
parent 9c4af6af7e
commit d556269810
4 changed files with 43 additions and 52 deletions

View File

@ -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>

View File

@ -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());

View File

@ -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 {

View File

@ -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);