/**
Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags
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 bftsmart.demo.microbenchmarks;
import bftsmart.statemanagement.StateManager;
import bftsmart.tom.MessageContext;
import bftsmart.tom.ReplicaContext;
import bftsmart.tom.ServiceReplica;
import bftsmart.tom.server.defaultservices.DefaultRecoverable;
import bftsmart.tom.util.Storage;
/**
* Simple server that just acknowledge the reception of a request.
*/
public class LatencyServer extends DefaultRecoverable{
private int interval;
private int replySize;
private int iterations = 0;
private Storage totalLatency = null;
private Storage consensusLatency = null;
private Storage preConsLatency = null;
private Storage posConsLatency = null;
private Storage proposeLatency = null;
private Storage writeLatency = null;
private Storage acceptLatency = null;
private ServiceReplica replica;
public LatencyServer(int id, int interval, int replySize) {
this.interval = interval;
this.replySize = replySize;
totalLatency = new Storage(interval);
consensusLatency = new Storage(interval);
preConsLatency = new Storage(interval);
posConsLatency = new Storage(interval);
proposeLatency = new Storage(interval);
writeLatency = new Storage(interval);
acceptLatency = new Storage(interval);
replica = new ServiceReplica(id, this, this);
}
@Override
public byte[] appExecuteUnordered(byte[] command, MessageContext msgCtx) {
return execute(command,msgCtx);
}
@Override
public byte[][] appExecuteBatch(byte[][] commands, MessageContext[] msgCtxs) {
byte[][] replies = new byte[commands.length][];
for (int i = 0; i < commands.length; i++) {
replies[i] = execute(commands[i],msgCtxs[i]);
}
return replies;
}
public byte[] execute(byte[] command, MessageContext msgCtx) {
boolean readOnly = false;
iterations++;
if (msgCtx != null && msgCtx.getFirstInBatch() != null) {
readOnly = msgCtx.readOnly;
msgCtx.getFirstInBatch().executedTime = System.nanoTime();
totalLatency.store(msgCtx.getFirstInBatch().executedTime - msgCtx.getFirstInBatch().receptionTime);
if (readOnly == false) {
consensusLatency.store(msgCtx.getFirstInBatch().decisionTime - msgCtx.getFirstInBatch().consensusStartTime);
long temp = msgCtx.getFirstInBatch().consensusStartTime - msgCtx.getFirstInBatch().receptionTime;
preConsLatency.store(temp > 0 ? temp : 0);
posConsLatency.store(msgCtx.getFirstInBatch().executedTime - msgCtx.getFirstInBatch().decisionTime);
proposeLatency.store(msgCtx.getFirstInBatch().writeSentTime - msgCtx.getFirstInBatch().consensusStartTime);
writeLatency.store(msgCtx.getFirstInBatch().acceptSentTime - msgCtx.getFirstInBatch().writeSentTime);
acceptLatency.store(msgCtx.getFirstInBatch().decisionTime - msgCtx.getFirstInBatch().acceptSentTime);
} else {
consensusLatency.store(0);
preConsLatency.store(0);
posConsLatency.store(0);
proposeLatency.store(0);
writeLatency.store(0);
acceptLatency.store(0);
}
} else {
consensusLatency.store(0);
preConsLatency.store(0);
posConsLatency.store(0);
proposeLatency.store(0);
writeLatency.store(0);
acceptLatency.store(0);
}
if(iterations % interval == 0) {
System.out.println("--- Measurements after "+ iterations+" ops ("+interval+" samples) ---");
System.out.println("Total latency = " + totalLatency.getAverage(false) / 1000 + " (+/- "+ (long)totalLatency.getDP(false) / 1000 +") us ");
totalLatency.reset();
System.out.println("Consensus latency = " + consensusLatency.getAverage(false) / 1000 + " (+/- "+ (long)consensusLatency.getDP(false) / 1000 +") us ");
consensusLatency.reset();
System.out.println("Pre-consensus latency = " + preConsLatency.getAverage(false) / 1000 + " (+/- "+ (long)preConsLatency.getDP(false) / 1000 +") us ");
preConsLatency.reset();
System.out.println("Pos-consensus latency = " + posConsLatency.getAverage(false) / 1000 + " (+/- "+ (long)posConsLatency.getDP(false) / 1000 +") us ");
posConsLatency.reset();
System.out.println("Propose latency = " + proposeLatency.getAverage(false) / 1000 + " (+/- "+ (long)proposeLatency.getDP(false) / 1000 +") us ");
proposeLatency.reset();
System.out.println("Write latency = " + writeLatency.getAverage(false) / 1000 + " (+/- "+ (long)writeLatency.getDP(false) / 1000 +") us ");
writeLatency.reset();
System.out.println("Accept latency = " + acceptLatency.getAverage(false) / 1000 + " (+/- "+ (long)acceptLatency.getDP(false) / 1000 +") us ");
acceptLatency.reset();
}
return new byte[replySize];
}
public static void main(String[] args){
if(args.length < 3) {
System.out.println("Use: java ...LatencyServer <processId> <measurement interval> <reply size>");
System.exit(-1);
}
int processId = Integer.parseInt(args[0]);
int interval = Integer.parseInt(args[1]);
int replySize = Integer.parseInt(args[2]);
new LatencyServer(processId,interval,replySize);
}
@Override
public void installSnapshot(byte[] state) {
}
@Override
public byte[] getSnapshot() {
return new byte[0];
}
}