/* * Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net> * Distributed under the terms of either: * - the common development and distribution license (CDDL), v1.0; or * - the GNU Lesser General Public License, v2.1 or later */ package winstone.testCase.load; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import winstone.Logger; import winstone.WebAppConfiguration; import winstone.WinstoneResourceBundle; import com.meterware.httpunit.WebConversation; /** * This class is an attempt to benchmark performance under load for winstone. It * works by hitting a supplied URL with parallel threads (with keep-alives or * without) at an escalating rate, and counting the no of failures. * * It uses HttpUnit's WebConversation class for the connection. * * @author <a href="mailto:rick_knowles@hotmail.com">Rick Knowles</a> * @version $Id: LoadTest.java,v 1.2 2006/02/28 07:32:49 rickknowles Exp $ */ public class LoadTest { private String url; private boolean useKeepAlives; private int startThreads; private int endThreads; private int stepSize; private long stepPeriod; private long gracePeriod; private long successTimeTotal; private int successCount; private WinstoneResourceBundle resources; private static String LOCAL_RESOURCE_FILE = "winstone.testCase.load.LocalStrings"; public LoadTest(WinstoneResourceBundle resources, String url, boolean useKeepAlives, int startThreads, int endThreads, int stepSize, long stepPeriod, long gracePeriod) { this.resources = resources; this.url = url; this.useKeepAlives = useKeepAlives; this.startThreads = startThreads; this.endThreads = endThreads; this.stepSize = stepSize; this.stepPeriod = stepPeriod; this.gracePeriod = gracePeriod; Logger.log(Logger.INFO, resources, "LoadTest.Config", new String[] { this.url, this.useKeepAlives + "", this.startThreads + "", this.endThreads + "", this.stepSize + "", this.stepPeriod + "", this.gracePeriod + "" }); } public void test() throws InterruptedException { WebConversation wc = null; // Loop through in steps for (int n = this.startThreads; n <= this.endThreads; n += this.stepSize) { if (this.useKeepAlives) wc = new WebConversation(); // Spawn the threads int noOfSeconds = (int) this.stepPeriod / 1000; List threads = new ArrayList(); for (int m = 0; m < n; m++) threads.add(new LoadTestThread(this.url, this, this.resources, wc, noOfSeconds - 1)); // Sleep for step period Thread.sleep(this.stepPeriod + gracePeriod); // int errorCount = (noOfSeconds * n) - this.successCount; Long averageSuccessTime = this.successCount == 0 ? null : new Long( this.successTimeTotal / this.successCount); // Write out results Logger.log(Logger.INFO, resources, "LoadTest.LineResult", new String[] { n + "", this.successCount + "", ((noOfSeconds * n) - this.successCount) + "", averageSuccessTime + "" }); // Close threads for (Iterator i = threads.iterator(); i.hasNext();) ((LoadTestThread) i.next()).destroy(); this.successTimeTotal = 0; this.successCount = 0; } } public void incTimeTotal(long amount) { this.successTimeTotal += amount; } public void incSuccessCount() { this.successCount++; } public static void main(String args[]) throws Exception { WinstoneResourceBundle resources = new WinstoneResourceBundle( LOCAL_RESOURCE_FILE); // Loop for args Map options = new HashMap(); // String operation = ""; for (int n = 0; n < args.length; n++) { String option = args[n]; if (option.startsWith("--")) { int equalPos = option.indexOf('='); String paramName = option.substring(2, equalPos == -1 ? option .length() : equalPos); String paramValue = (equalPos == -1 ? "true" : option .substring(equalPos + 1)); options.put(paramName, paramValue); } } if (options.size() == 0) { printUsage(resources); return; } Logger.setCurrentDebugLevel(Integer.parseInt(WebAppConfiguration .stringArg(options, "debug", "5"))); String url = WebAppConfiguration.stringArg(options, "url", "http://localhost:8080/"); boolean keepAlive = WebAppConfiguration.booleanArg(options, "keepAlive", true); String startThreads = WebAppConfiguration.stringArg(options, "startThreads", "20"); String endThreads = WebAppConfiguration.stringArg(options, "endThreads", "1000"); String stepSize = WebAppConfiguration.stringArg(options, "stepSize", "20"); String stepPeriod = WebAppConfiguration.stringArg(options, "stepPeriod", "5000"); String gracePeriod = WebAppConfiguration.stringArg(options, "gracePeriod", "5000"); LoadTest lt = new LoadTest(resources, url, keepAlive, Integer .parseInt(startThreads), Integer.parseInt(endThreads), Integer .parseInt(stepSize), Integer.parseInt(stepPeriod), Integer .parseInt(gracePeriod)); lt.test(); } /** * Displays the usage message */ private static void printUsage(WinstoneResourceBundle resources) throws IOException { System.out.println(resources.getString("LoadTest.Usage")); } }