Java tutorial
// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved. // // This software, the RabbitMQ Java client library, is triple-licensed under the // Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 // ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see // LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, // please see LICENSE-APACHE2. // // This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, // either express or implied. See the LICENSE file for specific language governing // rights and limitations of this software. // // If you have any questions regarding licensing, please contact us at // info@rabbitmq.com. package com.rabbitmq.perf; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.List; import com.rabbitmq.perf.MulticastParams; import com.rabbitmq.perf.MulticastSet; import com.rabbitmq.perf.Stats; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import com.rabbitmq.client.ConnectionFactory; public class PerfTest { public static void main(String[] args) { Options options = getOptions(); CommandLineParser parser = new GnuParser(); try { CommandLine cmd = parser.parse(options, args); if (cmd.hasOption('?')) { usage(options); System.exit(0); } String testID = new SimpleDateFormat("HHmmss-SSS").format(Calendar.getInstance().getTime()); testID = strArg(cmd, 'd', "test-" + testID); String exchangeType = strArg(cmd, 't', "direct"); String exchangeName = strArg(cmd, 'e', exchangeType); String queueNames = strArg(cmd, 'u', ""); String routingKey = strArg(cmd, 'k', null); boolean randomRoutingKey = cmd.hasOption('K'); int samplingInterval = intArg(cmd, 'i', 1); float producerRateLimit = floatArg(cmd, 'r', 0.0f); float consumerRateLimit = floatArg(cmd, 'R', 0.0f); int producerCount = intArg(cmd, 'x', 1); int consumerCount = intArg(cmd, 'y', 1); int producerTxSize = intArg(cmd, 'm', 0); int consumerTxSize = intArg(cmd, 'n', 0); long confirm = intArg(cmd, 'c', -1); boolean autoAck = cmd.hasOption('a'); int multiAckEvery = intArg(cmd, 'A', 0); int channelPrefetch = intArg(cmd, 'Q', 0); int consumerPrefetch = intArg(cmd, 'q', 0); int minMsgSize = intArg(cmd, 's', 0); int timeLimit = intArg(cmd, 'z', 0); int producerMsgCount = intArg(cmd, 'C', 0); int consumerMsgCount = intArg(cmd, 'D', 0); List<?> flags = lstArg(cmd, 'f'); int frameMax = intArg(cmd, 'M', 0); int heartbeat = intArg(cmd, 'b', 0); boolean predeclared = cmd.hasOption('p'); String uri = strArg(cmd, 'h', "amqp://localhost"); //setup PrintlnStats stats = new PrintlnStats(testID, 1000L * samplingInterval, producerCount > 0, consumerCount > 0, (flags.contains("mandatory") || flags.contains("immediate")), confirm != -1); ConnectionFactory factory = new ConnectionFactory(); factory.setShutdownTimeout(0); // So we still shut down even with slow consumers factory.setUri(uri); factory.setRequestedFrameMax(frameMax); factory.setRequestedHeartbeat(heartbeat); MulticastParams p = new MulticastParams(); p.setAutoAck(autoAck); p.setAutoDelete(true); p.setConfirm(confirm); p.setConsumerCount(consumerCount); p.setConsumerMsgCount(consumerMsgCount); p.setConsumerRateLimit(consumerRateLimit); p.setConsumerTxSize(consumerTxSize); p.setExchangeName(exchangeName); p.setExchangeType(exchangeType); p.setFlags(flags); p.setMultiAckEvery(multiAckEvery); p.setMinMsgSize(minMsgSize); p.setPredeclared(predeclared); p.setConsumerPrefetch(consumerPrefetch); p.setChannelPrefetch(channelPrefetch); p.setProducerCount(producerCount); p.setProducerMsgCount(producerMsgCount); p.setProducerTxSize(producerTxSize); p.setQueueNames(Arrays.asList(queueNames.split(","))); p.setRoutingKey(routingKey); p.setRandomRoutingKey(randomRoutingKey); p.setProducerRateLimit(producerRateLimit); p.setTimeLimit(timeLimit); MulticastSet set = new MulticastSet(stats, factory, p, testID); set.run(true); stats.printFinal(); } catch (ParseException exp) { System.err.println("Parsing failed. Reason: " + exp.getMessage()); usage(options); } catch (Exception e) { System.err.println("Main thread caught exception: " + e); e.printStackTrace(); System.exit(1); } } private static void usage(Options options) { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp("<program>", options); } private static Options getOptions() { Options options = new Options(); options.addOption(new Option("?", "help", false, "show usage")); options.addOption(new Option("d", "id", true, "test ID")); options.addOption(new Option("h", "uri", true, "connection URI")); options.addOption(new Option("t", "type", true, "exchange type")); options.addOption(new Option("e", "exchange", true, "exchange name")); options.addOption(new Option("u", "queue", true, "queue name")); options.addOption(new Option("k", "routingKey", true, "routing key")); options.addOption(new Option("K", "randomRoutingKey", false, "use random routing key per message")); options.addOption(new Option("i", "interval", true, "sampling interval in seconds")); options.addOption(new Option("r", "rate", true, "producer rate limit")); options.addOption(new Option("R", "consumerRate", true, "consumer rate limit")); options.addOption(new Option("x", "producers", true, "producer count")); options.addOption(new Option("y", "consumers", true, "consumer count")); options.addOption(new Option("m", "ptxsize", true, "producer tx size")); options.addOption(new Option("n", "ctxsize", true, "consumer tx size")); options.addOption(new Option("c", "confirm", true, "max unconfirmed publishes")); options.addOption(new Option("a", "autoack", false, "auto ack")); options.addOption(new Option("A", "multiAckEvery", true, "multi ack every")); options.addOption(new Option("q", "qos", true, "consumer prefetch count")); options.addOption(new Option("Q", "globalQos", true, "channel prefetch count")); options.addOption(new Option("s", "size", true, "message size in bytes")); options.addOption(new Option("z", "time", true, "run duration in seconds (unlimited by default)")); options.addOption(new Option("C", "pmessages", true, "producer message count")); options.addOption(new Option("D", "cmessages", true, "consumer message count")); Option flag = new Option("f", "flag", true, "message flag"); flag.setArgs(Option.UNLIMITED_VALUES); options.addOption(flag); options.addOption(new Option("M", "framemax", true, "frame max")); options.addOption(new Option("b", "heartbeat", true, "heartbeat interval")); options.addOption(new Option("p", "predeclared", false, "allow use of predeclared objects")); return options; } private static String strArg(CommandLine cmd, char opt, String def) { return cmd.getOptionValue(opt, def); } private static int intArg(CommandLine cmd, char opt, int def) { return Integer.parseInt(cmd.getOptionValue(opt, Integer.toString(def))); } private static float floatArg(CommandLine cmd, char opt, float def) { return Float.parseFloat(cmd.getOptionValue(opt, Float.toString(def))); } private static List<?> lstArg(CommandLine cmd, char opt) { String[] vals = cmd.getOptionValues('f'); if (vals == null) { vals = new String[] {}; } return Arrays.asList(vals); } private static class PrintlnStats extends Stats { private final boolean sendStatsEnabled; private final boolean recvStatsEnabled; private final boolean returnStatsEnabled; private final boolean confirmStatsEnabled; private final String testID; public PrintlnStats(String testID, long interval, boolean sendStatsEnabled, boolean recvStatsEnabled, boolean returnStatsEnabled, boolean confirmStatsEnabled) { super(interval); this.sendStatsEnabled = sendStatsEnabled; this.recvStatsEnabled = recvStatsEnabled; this.returnStatsEnabled = returnStatsEnabled; this.confirmStatsEnabled = confirmStatsEnabled; this.testID = testID; } @Override protected void report(long now) { String output = "id: " + testID + ", "; output += "time: " + String.format("%.3f", (now - startTime) / 1000.0) + "s"; output += getRate("sent", sendCountInterval, sendStatsEnabled, elapsedInterval) + getRate("returned", returnCountInterval, sendStatsEnabled && returnStatsEnabled, elapsedInterval) + getRate("confirmed", confirmCountInterval, sendStatsEnabled && confirmStatsEnabled, elapsedInterval) + getRate("nacked", nackCountInterval, sendStatsEnabled && confirmStatsEnabled, elapsedInterval) + getRate("received", recvCountInterval, recvStatsEnabled, elapsedInterval); output += (latencyCountInterval > 0 ? ", min/avg/max latency: " + minLatency / 1000L + "/" + cumulativeLatencyInterval / (1000L * latencyCountInterval) + "/" + maxLatency / 1000L + " microseconds" : ""); System.out.println(output); } private String getRate(String descr, long count, boolean display, long elapsed) { if (display) return ", " + descr + ": " + formatRate(1000.0 * count / elapsed) + " msg/s"; else return ""; } public void printFinal() { long now = System.currentTimeMillis(); System.out.println("id: " + testID + ", sending rate avg: " + formatRate(sendCountTotal * 1000.0 / (now - startTime)) + " msg/s"); long elapsed = now - startTime; if (elapsed > 0) { System.out.println("id: " + testID + ", recving rate avg: " + formatRate(recvCountTotal * 1000.0 / elapsed) + " msg/s"); } } private static String formatRate(double rate) { if (rate == 0.0) return String.format("%d", (long) rate); else if (rate < 1) return String.format("%1.2f", rate); else if (rate < 10) return String.format("%1.1f", rate); else return String.format("%d", (long) rate); } } }