import com.sun.istack.internal.NotNull; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.concurrent.atomic.AtomicInteger; public class LatencyPercentileTests implements ITestScenario{ private AtomicInteger threadCounter = new AtomicInteger(0); private ArrayList<Double> aggregatedData = new ArrayList<Double>(); private static DecimalFormat dblFormat = new DecimalFormat("###.#"); public void run(@NotNull CommandLineArgs options) { int threads = options.getThreadCount(); int iterations = options.getIterationCount(); ArrayList<WorkerThread> list = new ArrayList<WorkerThread>(); try { Logging.writeLine("Starting %d thread(s), %d iteration(s), using client %s", threads, iterations, Redis.getClient().getClass().getSimpleName()); for(int i = 0; i < threads; i++) list.add(startLoadTest(iterations)); Thread.sleep(1000); Logging.writeLine("\r\nwaiting for iterations to complete..."); while(list.size() > 0) { WorkerThread t = list.remove(0); while (t.isAlive()) { Logging.write("."); Thread.sleep(1000); } } Logging.writeLine("\r\nResult aggregation complete..."); printResults(); } catch(Exception ex) { Logging.logException(ex); } } private void printResults() { Logging.writeLine( "--------------------------------------------------"); Collections.sort(aggregatedData); int count = aggregatedData.size(); Logging.writeLine(String.format("Request Count: %d", count)); Logging.writeLine(getPercentile(50.0)); Logging.writeLine(getPercentile(80.0)); Logging.writeLine(getPercentile(90.0)); Logging.writeLine(getPercentile(95.0)); Logging.writeLine(getPercentile(98.0)); Logging.writeLine(getPercentile(99.0)); Logging.writeLine(getPercentile(99.5)); Logging.writeLine(getPercentile(99.9)); Logging.writeLine(getPercentile(100.0)); Logging.writeLine( "--------------------------------------------------"); } private String getPercentile(Double percentile) { int count = aggregatedData.size(); int index = (int)Math.floor((percentile/100) * count); if (index == count) index = count - 1; Double val = aggregatedData.get(index); return String.format("%5sth Percentile : %sms", dblFormat.format(percentile), dblFormat.format(val)); } private WorkerThread startLoadTest(int iterations) { Worker work = new Worker(){ @Override public void run() { ArrayList<Double> times = new ArrayList<Double>(); int threadId = threadCounter.incrementAndGet(); Logging.write("|" + threadId); String key = "foo:" + Program.AppName + ":" + Integer.toString(threadId); String value = new Date().toString(); int warmUpCount = Math.max(iterations / 10, 300); Redis.getClient().set(key, value); //Logging.writeLine("\r\nStarting warmup with %d iterations.", warmUpCount); for(int i = 0; i < warmUpCount; i ++) Redis.getClient().get(key); //Logging.writeLine("\r\nStarting real latency tests..."); for(int i = 0; i < iterations; i++){ if (i % 1000 == 0) Logging.write(String.format("[%d/%d]", i, iterations)); IRedisClient client = Redis.getClient(); long start = Stopwatch.startNew(); client.get(key); Double duration = Stopwatch.elapsedMillis(start); times.add(duration); if (getStopRequested()) break; } Logging.write("#"); AggregateResults(times); } }; return WorkerThread.start(work); } private synchronized void AggregateResults(ArrayList<Double> threadResults) { aggregatedData.addAll(threadResults); } }