/*
* Copyright (c) 2012-2013 Spotify AB
*
* Licensed 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.
*/
package com.spotify.netty4.handler.codec.zmtp;
import com.google.common.collect.Lists;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.List;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;
import static com.spotify.netty4.handler.codec.zmtp.ZMTPVersion.ZMTP10;
import static com.spotify.netty4.handler.codec.zmtp.ZMTPVersion.ZMTP20;
import static com.spotify.netty4.handler.codec.zmtp.ZMTPWireFormats.wireFormat;
// FIXME (dano): this benchmark needs to be in this package because it uses some internals
@State(Scope.Benchmark)
public class CodecBenchmark {
private final List<Object> out = Lists.newArrayList();
private final ZMTPMessage message = ZMTPMessage.fromUTF8(
"first identity frame",
"second identity frame",
"",
"datadatadatadatadatadatadatadatadatadata",
"datadatadatadatadatadatadatadatadatadata",
"datadatadatadatadatadatadatadatadatadata",
"datadatadatadatadatadatadatadatadatadata");
private final ZMTPFramingDecoder messageDecoderZMTP10 =
new ZMTPFramingDecoder(wireFormat(ZMTP10), new ZMTPMessageDecoder());
private final ZMTPFramingDecoder messageDecoderZMTP20 =
new ZMTPFramingDecoder(wireFormat(ZMTP20), new ZMTPMessageDecoder());
private final ZMTPFramingDecoder discardingDecoderZMTP10 =
new ZMTPFramingDecoder(wireFormat(ZMTP10), new Discarder());
private final ZMTPFramingDecoder discardingDecoderZMTP20 =
new ZMTPFramingDecoder(wireFormat(ZMTP20), new Discarder());
private final ByteBuf incomingZMTP10;
private final ByteBuf incomingZMTP20;
private final ZMTPMessageEncoder encoder = new ZMTPMessageEncoder();
private final ZMTPWriter writerZMTP10 = ZMTPWriter.create(ZMTP10);
private final ZMTPWriter writerZMTP20 = ZMTPWriter.create(ZMTP20);
private final ByteBuf tmp = PooledByteBufAllocator.DEFAULT.buffer(4096);
{
incomingZMTP10 = message.write(PooledByteBufAllocator.DEFAULT, ZMTP10);
incomingZMTP20 = message.write(PooledByteBufAllocator.DEFAULT, ZMTP20);
}
@SuppressWarnings("ForLoopReplaceableByForEach")
private void consumeAndRelease(final Blackhole bh, final List<Object> out) {
for (int i = 0; i < out.size(); i++) {
final Object o = out.get(i);
bh.consume(o);
ReferenceCountUtil.release(o);
}
out.clear();
}
@Benchmark
public void parsingToMessageZMTP10(final Blackhole bh) throws ZMTPParsingException {
messageDecoderZMTP10.decode(null, incomingZMTP10.resetReaderIndex(), out);
consumeAndRelease(bh, out);
}
@Benchmark
public void parsingToMessageZMTP20(final Blackhole bh) throws ZMTPParsingException {
messageDecoderZMTP20.decode(null, incomingZMTP20.resetReaderIndex(), out);
consumeAndRelease(bh, out);
}
@Benchmark
public void discardingZMTP10(final Blackhole bh) throws ZMTPParsingException {
discardingDecoderZMTP10.decode(null, incomingZMTP10.resetReaderIndex(), out);
consumeAndRelease(bh, out);
}
@Benchmark
public void discardingZMTP20(final Blackhole bh) throws ZMTPParsingException {
discardingDecoderZMTP20.decode(null, incomingZMTP20.resetReaderIndex(), out);
consumeAndRelease(bh, out);
}
@Benchmark
public Object encodingZMTP10() {
writerZMTP10.reset(tmp.setIndex(0, 0));
encoder.encode(message, writerZMTP10);
return tmp;
}
@Benchmark
public Object encodingZMTP20() {
writerZMTP20.reset(tmp.setIndex(0, 0));
encoder.encode(message, writerZMTP20);
return tmp;
}
public static void main(final String... args) throws RunnerException, InterruptedException {
Options opt = new OptionsBuilder()
.include(".*")
.forks(1)
.build();
new Runner(opt).run();
}
private class Discarder implements ZMTPDecoder {
private int size;
@Override
public void header(final ChannelHandlerContext ctx, final long length, final boolean more,
final List<Object> out) {
this.size += size;
}
@Override
public void content(final ChannelHandlerContext ctx, final ByteBuf data,
final List<Object> out) {
data.skipBytes(data.readableBytes());
}
@Override
public void finish(final ChannelHandlerContext ctx, final List<Object> out) {
}
@Override
public void close() {
}
}
}