/*
* Copyright 2011-2016 the original author or authors.
*
* 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.lambdaworks.redis.protocol;
import java.util.ArrayDeque;
import java.util.Collection;
import org.openjdk.jmh.annotations.*;
import com.lambdaworks.redis.ClientOptions;
import com.lambdaworks.redis.codec.ByteArrayCodec;
import com.lambdaworks.redis.output.ValueOutput;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelPromise;
import io.netty.channel.embedded.EmbeddedChannel;
/**
* Benchmark for {@link CommandHandler}. Test cases:
* <ul>
* <li>user command writes</li>
* <li>netty (in-eventloop) writes</li>
* </ul>
*
* @author Mark Paluch
*/
@State(Scope.Benchmark)
public class CommandHandlerBenchmark {
private final static ByteArrayCodec CODEC = new ByteArrayCodec();
private final static ClientOptions CLIENT_OPTIONS = ClientOptions.create();
private final static EmptyContext CHANNEL_HANDLER_CONTEXT = new EmptyContext();
private final static byte[] KEY = "key".getBytes();
private final static ChannelFuture EMPTY = new EmptyFuture();
private CommandHandler commandHandler;
private Collection<?> transportBuffer;
private Command command;
@Setup
public void setup() {
commandHandler = new CommandHandler(CLIENT_OPTIONS, EmptyClientResources.INSTANCE, new ArrayDeque<>()) {
@Override
protected void setState(LifecycleState lifecycleState) {
CommandHandlerBenchmark.this.transportBuffer = super.transportBuffer;
super.setState(lifecycleState);
}
};
command = new Command(CommandType.GET, new ValueOutput<>(CODEC), new CommandArgs(CODEC).addKey(KEY));
commandHandler.setState(CommandHandler.LifecycleState.CONNECTED);
commandHandler.channel = new MyLocalChannel();
}
@TearDown(Level.Iteration)
public void tearDown() {
commandHandler.reset();
transportBuffer.clear();
}
@Benchmark
public void measureUserWrite() {
commandHandler.write(command);
}
@Benchmark
public void measureNettyWrite() throws Exception {
commandHandler.write(CHANNEL_HANDLER_CONTEXT, command, null);
}
private final static class MyLocalChannel extends EmbeddedChannel {
@Override
public boolean isActive() {
return true;
}
@Override
public boolean isOpen() {
return true;
}
@Override
public ChannelFuture write(Object msg) {
return EMPTY;
}
@Override
public ChannelFuture write(Object msg, ChannelPromise promise) {
return promise;
}
@Override
public ChannelFuture writeAndFlush(Object msg) {
return EMPTY;
}
@Override
public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
return promise;
}
}
}