/** 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]; } }