Have microbenchmarks produce a deployable artifact. Fix some minor miscellaneous issues.

Motivation:
Allows for running benchmarks from built jars which is useful in development environments that only take released artifacts.

Modifications:
Move benchmarks into 'main' from 'test'
Add @State annotations to benchmarks that are missing them
Fix timing issue grabbing context during channel initialization

Result:
Users can run benchmarks more easily.
This commit is contained in:
Louis Ryan 2015-04-13 15:45:48 -07:00 committed by Scott Mitchell
parent e48e6e4509
commit f3fb77f4bc
26 changed files with 227 additions and 27 deletions

View File

@ -70,6 +70,11 @@
<version>${project.version}</version> <version>${project.version}</version>
<classifier>linux-${epoll.arch}</classifier> <classifier>linux-${epoll.arch}</classifier>
</dependency> </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>org.openjdk.jmh</groupId> <groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId> <artifactId>jmh-core</artifactId>
@ -90,25 +95,49 @@
<build> <build>
<plugins> <plugins>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<configuration> <configuration>
<testSourceDirectory>${project.build.sourceDirectory}</testSourceDirectory>
<testClassesDirectory>${project.build.outputDirectory}</testClassesDirectory>
<excludes> <excludes>
<exclude>**/AbstractMicrobenchmark.java</exclude> <exclude>**/AbstractMicrobenchmark.java</exclude>
<exclude>**/*$*.class</exclude> <exclude>**/*$*.class</exclude>
<exclude>**/generated/*.class</exclude>
</excludes> </excludes>
<systemPropertyVariables> <systemPropertyVariables>
<perfReportDir>${project.build.directory}/reports/performance/</perfReportDir> <perfReportDir>${project.build.directory}/reports/performance/</perfReportDir>
</systemPropertyVariables> </systemPropertyVariables>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<executions>
<execution>
<id>generate-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
<configuration>
<supportedProjectTypes>
<supportedProjectType>jar</supportedProjectType>
<supportedProjectType>bundle</supportedProjectType>
</supportedProjectTypes>
<instructions>
<Export-Package>${project.groupId}.*</Export-Package>
<Export-Package>!*.generated.*</Export-Package>
<!-- enforce JVM vendor package as optional -->
<Import-Package>sun.nio.ch;resolution:=optional,org.eclipse.jetty.npn;version="[1,2)";resolution:=optional,org.eclipse.jetty.alpn;version="[1,2)";resolution:=optional,*</Import-Package>
<!-- override "internal" private package convention -->
<Private-Package>!*</Private-Package>
</instructions>
</configuration>
</execution>
</executions>
</plugin>
</plugins> </plugins>
<extensions> <extensions>
<extension> <extension>

View File

@ -22,12 +22,15 @@ import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.microbench.util.AbstractMicrobenchmark; import io.netty.microbench.util.AbstractMicrobenchmark;
import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import java.util.Random; import java.util.Random;
/** /**
* This class benchmarks different allocators with different allocation sizes. * This class benchmarks different allocators with different allocation sizes.
*/ */
@State(Scope.Benchmark)
public class ByteBufAllocatorBenchmark extends AbstractMicrobenchmark { public class ByteBufAllocatorBenchmark extends AbstractMicrobenchmark {
private static final ByteBufAllocator unpooledAllocator = new UnpooledByteBufAllocator(true); private static final ByteBufAllocator unpooledAllocator = new UnpooledByteBufAllocator(true);

View File

@ -0,0 +1,19 @@
/*
* Copyright 2015 The Netty Project
*
* 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
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Benchmarks for {@link io.netty.buffer}.
*/
package io.netty.microbench.buffer;

View File

@ -0,0 +1,19 @@
/*
* Copyright 2015 The Netty Project
*
* 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
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Benchmarks for {@link io.netty.channel}.
*/
package io.netty.microbench.channel;

View File

@ -0,0 +1,19 @@
/*
* Copyright 2015 The Netty Project
*
* 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
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Benchmarks for {@link io.netty.util.concurrent}.
*/
package io.netty.microbench.concurrent;

View File

@ -0,0 +1,19 @@
/*
* Copyright 2015 The Netty Project
*
* 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
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Benchmarks for {@link io.netty.handler.codec.http}.
*/
package io.netty.microbench.http;

View File

@ -18,6 +18,8 @@ import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_MAX_FRAME_SIZE
import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_FRAME_SIZE_UPPER_BOUND; import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_FRAME_SIZE_UPPER_BOUND;
import static io.netty.util.internal.ObjectUtil.checkNotNull; import static io.netty.util.internal.ObjectUtil.checkNotNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap; import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
@ -66,6 +68,7 @@ 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.Random; import java.util.Random;
import java.util.concurrent.CountDownLatch;
import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Level; import org.openjdk.jmh.annotations.Level;
@ -226,7 +229,7 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
final EnvironmentParameters params = environmentType.params(); 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 TransportEnvironment environment = new TransportEnvironment(cb, sb);
EventLoopGroup serverEventLoopGroup = params.newEventLoopGroup(); EventLoopGroup serverEventLoopGroup = params.newEventLoopGroup();
sb.group(serverEventLoopGroup, serverEventLoopGroup); sb.group(serverEventLoopGroup, serverEventLoopGroup);
@ -242,6 +245,7 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
cb.group(params.newEventLoopGroup()); cb.group(params.newEventLoopGroup());
cb.channel(params.clientChannelClass()); cb.channel(params.clientChannelClass());
cb.option(ChannelOption.ALLOCATOR, params.clientAllocator()); cb.option(ChannelOption.ALLOCATOR, params.clientAllocator());
final CountDownLatch latch = new CountDownLatch(1);
cb.handler(new ChannelInitializer<Channel>() { cb.handler(new ChannelInitializer<Channel>() {
@Override @Override
protected void initChannel(Channel ch) throws Exception { protected void initChannel(Channel ch) throws Exception {
@ -263,12 +267,21 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
Http2ConnectionHandler connectionHandler = new Http2ConnectionHandler(decoder, encoder); Http2ConnectionHandler connectionHandler = new Http2ConnectionHandler(decoder, encoder);
p.addLast(connectionHandler); p.addLast(connectionHandler);
environment.context(p.lastContext()); environment.context(p.lastContext());
// Must wait for context to be set.
latch.countDown();
} }
}); });
environment.serverChannel(sb.bind(params.address())); environment.serverChannel(sb.bind(params.address()));
params.address(environment.serverChannel().localAddress()); params.address(environment.serverChannel().localAddress());
environment.clientChannel(cb.connect(params.address())); environment.clientChannel(cb.connect(params.address()));
try {
if (!latch.await(5, SECONDS)) {
throw new RuntimeException("Channel did not initialize in time");
}
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
return environment; return environment;
} }
@ -437,7 +450,7 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
} }
} }
private static final class TrasportEnvironment implements Environment { private static final class TransportEnvironment implements Environment {
private final ServerBootstrap sb; private final ServerBootstrap sb;
private final Bootstrap cb; private final Bootstrap cb;
private Channel serverChannel; private Channel serverChannel;
@ -445,7 +458,7 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
private ChannelHandlerContext clientContext; private ChannelHandlerContext clientContext;
private Http2FrameWriter clientWriter; private Http2FrameWriter clientWriter;
public TrasportEnvironment(Bootstrap cb, ServerBootstrap sb) { public TransportEnvironment(Bootstrap cb, ServerBootstrap sb) {
this.sb = checkNotNull(sb, "sb"); this.sb = checkNotNull(sb, "sb");
this.cb = checkNotNull(cb, "cb"); this.cb = checkNotNull(cb, "cb");
} }

View File

@ -0,0 +1,19 @@
/*
* Copyright 2015 The Netty Project
*
* 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
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Benchmarks for {@link io.netty.handler.codec.http2}.
*/
package io.netty.microbench.http2;

View File

@ -20,11 +20,14 @@ import io.netty.util.internal.RecyclableArrayList;
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.Param; import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads; import org.openjdk.jmh.annotations.Threads;
/** /**
* This class benchmarks different allocators with different allocation sizes. * This class benchmarks different allocators with different allocation sizes.
*/ */
@State(Scope.Benchmark)
@Threads(4) @Threads(4)
@Measurement(iterations = 10, batchSize = 100) @Measurement(iterations = 10, batchSize = 100)
public class RecyclableArrayListBenchmark extends AbstractMicrobenchmark { public class RecyclableArrayListBenchmark extends AbstractMicrobenchmark {

View File

@ -0,0 +1,19 @@
/*
* Copyright 2015 The Netty Project
*
* 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
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Benchmarks for {@link io.netty.util.internal}.
*/
package io.netty.microbench.internal;

View File

@ -37,7 +37,7 @@ public class AbstractMicrobenchmark extends AbstractMicrobenchmarkBase {
static { static {
final String[] customArgs = { final String[] customArgs = {
"-Xms768m", "-Xmx768m", "-XX:MaxDirectMemorySize=768m", "-Dharness.executor=CUSTOM", "-Xms768m", "-Xmx768m", "-XX:MaxDirectMemorySize=768m", "-Dharness.executor=CUSTOM",
"-Dharness.executor.class=io.netty.microbench.util.AbstractMicrobenchmark$HarnessExecutor" }; "-Dharness.executor.class=AbstractMicrobenchmark$HarnessExecutor" };
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);

View File

@ -39,7 +39,7 @@ public class AbstractSharedExecutorMicrobenchmark extends AbstractMicrobenchmark
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.AbstractSharedExecutorMicrobenchmark$DelegateHarnessExecutor" }; "-Dharness.executor.class=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);

View File

@ -0,0 +1,19 @@
/*
* Copyright 2015 The Netty Project
*
* 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
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Benchmarks for {@link io.netty.util}.
*/
package io.netty.microbench.util;

View File

@ -0,0 +1,19 @@
/*
* Copyright 2015 The Netty Project
*
* 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
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Benchmarks for {@link io.netty.util}.
*/
package io.netty.microbenchmark.common;