Java tutorial
/** * Copyright (C) 2010-2013 Leon Blakey <lord.quackstar at gmail.com> * * This file is part of PircBotX. * * PircBotX is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * PircBotX is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with PircBotX. If not, see <http://www.gnu.org/licenses/>. */ package org.pircbotx; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.joran.JoranConfigurator; import ch.qos.logback.core.util.StatusPrinter; import com.google.common.io.ByteStreams; import java.io.IOException; import java.io.OutputStreamWriter; import java.security.SecureRandom; import java.util.Random; import java.util.concurrent.Executors; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.StopWatch; import org.pircbotx.exception.IrcException; import org.pircbotx.hooks.managers.GenericListenerManager; import org.pircbotx.hooks.managers.ListenerManager; import org.pircbotx.hooks.managers.ThreadedListenerManager; import org.pircbotx.impl.PircBotXJMeter; import org.pircbotx.output.OutputRaw; import org.slf4j.LoggerFactory; /** * * @author Leon */ public class Benchmark { protected final static int MAX_USERS = 200; protected final static int MAX_CHANNELS = 20; protected final static int MAX_ITERATIONS = 5; protected static String[][] responseGroups; protected static InputParser inputParser; public static void main(String[] args) throws Exception { //Change logging to no-op LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(context); context.reset(); configurator.doConfigure(Benchmark.class.getResource("/logback-nop.xml")); StatusPrinter.printInCaseOfErrorsOrWarnings(context); if (args.length != 1) { System.err.println("Must specify thread count:"); System.err.println(" -1: GenericListenerManager"); System.err.println(" 0: ThreadedListenerManager (default threads)"); System.err.println(" 1+: ThreadedListenerManager (specified threads)"); return; } int threadCount = Integer.parseInt(args[0]); //Init String[][] responseTemplateGroups = new String[13][]; responseTemplateGroups[0] = new String[] { ":${thisNick}!~jmeter@bots.jmeter PRIVMSG ${channel} ?jmeter ${thisNick}" }; responseTemplateGroups[1] = new String[] { ":${thisNick}!~jmeter@bots.jmeter PRIVMSG ${targetNick} ?jmeter ${thisNick}" }; responseTemplateGroups[2] = new String[] { ":${thisNick}!~jmeter@bots.jmeter PRIVMSG ${channel} :${thisNick}" }; responseTemplateGroups[3] = new String[] { ":${thisNick}!~jmeter@bots.jmeter PRIVMSG ${channel} :\u0001ACTION ${thisNick}\u0001" }; responseTemplateGroups[4] = new String[] { ":${thisNick}!~jmeter@bots.jmeter NOTICE ${channel} :${thisNick}" }; responseTemplateGroups[5] = new String[] { ":${thisNick}!~jmeter@bots.jmeter PRIVMSG ${targetNick} :${thisNick}" }; responseTemplateGroups[6] = new String[] { ":${thisNick}!~jmeter@bots.jmeter PRIVMSG ${targetNick} :\u0001ACTION ${thisNick}\u0001" }; responseTemplateGroups[7] = new String[] { ":${thisNick}!~jmeter@bots.jmeter MODE ${channel} +o ${thisNick}", ":${thisNick}!~jmeter@bots.jmeter MODE ${channel} -o ${thisNick}" }; responseTemplateGroups[8] = new String[] { ":${thisNick}!~jmeter@bots.jmeter MODE ${channel} +v ${thisNick}", ":${thisNick}!~jmeter@bots.jmeter MODE ${channel} -v ${thisNick}" }; responseTemplateGroups[9] = new String[] { ":${thisNick}!~jmeter@bots.jmeter KICK ${channel} ${targetNick}: ${thisNick}", ":${thisNick}!~jmeter@bots.jmeter JOIN :${channel}" }; responseTemplateGroups[10] = new String[] { ":${thisNick}!~jmeter@bots.jmeter MODE ${channel} +b ${thisNick}!*@*", ":${thisNick}!~jmeter@bots.jmeter MODE ${channel} -b ${thisNick}!*@*" }; responseTemplateGroups[11] = new String[] { ":${thisNick}!~jmeter@bots.jmeter PART ${channel}", ":${thisNick}!~jmeter@bots.jmeter JOIN :${channel}" }; responseTemplateGroups[12] = new String[] { ":${thisNick}!~jmeter@bots.jmeter QUIT :${thisNick}", ":${thisNick}!~jmeter@bots.jmeter JOIN :${channel}" }; Runtime runtime = Runtime.getRuntime(); System.out.println("Memory usage: " + (runtime.totalMemory() / 1024)); System.out.println("Building responses"); responseGroups = new String[MAX_USERS * MAX_CHANNELS * MAX_ITERATIONS * responseTemplateGroups.length][]; int responseGroupsCounter = 0; SecureRandom sortRandom = new SecureRandom(); String[] searchList = new String[] { "${thisNick}", "${channel}" }; for (int userNum = 0; userNum < MAX_USERS; userNum++) { shuffleArray(responseTemplateGroups, sortRandom); for (int channelNum = 0; channelNum < MAX_CHANNELS; channelNum++) { String[] replaceList = new String[] { "umark" + userNum, "#cbench" + channelNum }; for (int iterationNum = 0; iterationNum < MAX_ITERATIONS; iterationNum++) //Parse template for (int templateNum = 0, templateSize = responseTemplateGroups.length; templateNum < templateSize; templateNum++) { String[] templateGroup = responseTemplateGroups[templateNum]; String[] responseGroup = new String[templateGroup.length]; int responseCounter = 0; for (int templateLineNum = 0, templateLineSize = templateGroup.length; templateLineNum < templateLineSize; templateLineNum++) responseGroup[responseCounter++] = StringUtils .replaceEachRepeatedly(templateGroup[templateLineNum], searchList, replaceList); responseGroups[responseGroupsCounter++] = responseGroup; } } } System.out.println("Sorting"); shuffleArray(responseGroups, sortRandom); //Init other objects StopWatch stopWatch = new StopWatch(); ListenerManager listenerManager; if (threadCount == -1) listenerManager = new GenericListenerManager(); else if (threadCount == 0) listenerManager = new ThreadedListenerManager(Executors.newCachedThreadPool()); else listenerManager = new ThreadedListenerManager(Executors.newFixedThreadPool(threadCount)); PircBotX bot = new PircBotX(TestUtils.generateConfigurationBuilder().setListenerManager(listenerManager) .addListener(new PircBotXJMeter()).buildConfiguration()) { @Override public boolean isConnected() { return true; } @Override protected void sendRawLineToServer(String line) { //Do nothing } }; inputParser = bot.getInputParser(); System.out.println("Waiting 5 seconds"); Thread.sleep(5000); System.out.println("Executing with " + responseGroups.length + " response groups"); int counter = run(stopWatch); System.out.println("Parsed " + counter + " enteries in " + stopWatch.toString()); System.out.println( "Average parse speed: " + ((float) counter / (stopWatch.getTime() / 1000)) + " per second"); System.out.println("Memory usage: " + (runtime.totalMemory() / 1024)); //Kill the listener manager so the JVM can shutdown if (listenerManager instanceof ThreadedListenerManager) ((ThreadedListenerManager) listenerManager).shutdown(); } /** * Copied from Collections.shuffle and Collections.swap, this is actually what * they do, just on Collections instead of arrays * @param array * @return */ private static final void shuffleArray(String[][] array, Random rnd) { for (int i = array.length; i > 1; i--) { int j = rnd.nextInt(i); String[] tmp = array[i - 1]; array[i - 1] = array[j]; array[j] = tmp; } } private static final int run(StopWatch stopWatch) throws IOException, IrcException { int counter = 0; stopWatch.start(); for (String[] curGroup : responseGroups) { int size = curGroup.length; counter += size; for (int i = 0; i < size; i++) inputParser.handleLine(curGroup[i]); } stopWatch.stop(); return counter; } }