Author: psteitz Date: Thu Jul 26 23:10:54 2007 New Revision: 560120 URL: http://svn.apache.org/viewvc?view=rev&rev=560120 Log: Factored out common base of load generators. Also added support for sustained peak/trough periods.
Added: jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/LoadGenerator.java (with props) Modified: jakarta/commons/sandbox/performance/trunk/README.txt jakarta/commons/sandbox/performance/trunk/config-dbcp.xml jakarta/commons/sandbox/performance/trunk/config-pool.xml jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/ClientThread.java jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPClientThread.java jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPSoak.java jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPTest.java jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolClientThread.java jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolSoak.java jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolTest.java Modified: jakarta/commons/sandbox/performance/trunk/README.txt URL: http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/trunk/README.txt?view=diff&rev=560120&r1=560119&r2=560120 ============================================================================== --- jakarta/commons/sandbox/performance/trunk/README.txt (original) +++ jakarta/commons/sandbox/performance/trunk/README.txt Thu Jul 26 23:10:54 2007 @@ -1,4 +1,4 @@ -=== Compiling and running === +=== Compiling and running the dbcp and pool tests === To run the dbcp tests, edit configuration in config-dbcp.xml, make sure the configured database is running and accepting connections, and run @@ -33,13 +33,18 @@ consider increasing the number of service nodes (pool maxActive) or decreasing the delay-min / delay-max. +=== Making other load test runners === + +PoolClientThread, and PoolSoak (or the corresponding DBCP classes) illustrate +how to subclass ClientThread and LoadGenerator to create load tests. LoadGenerators +spawn ClientThreads, set them running and gather statistics. See the class +javadoc for ClientThread and LoadGenerator for details. + + === TODO === * Property representation and management is poor. Configuration objects should be defined and Digester should create and populate configuration beans. - -* There is still a fair amount of duplicated / similar code between pool and - dbcp. This should all be factored out and moved to the performance package. * Ant build is lame. To change pool impls used - e.g. to grab latest snap - you need to hack the get-deps. This should be cleaned up. Modified: jakarta/commons/sandbox/performance/trunk/config-dbcp.xml URL: http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/trunk/config-dbcp.xml?view=diff&rev=560120&r1=560119&r2=560120 ============================================================================== --- jakarta/commons/sandbox/performance/trunk/config-dbcp.xml (original) +++ jakarta/commons/sandbox/performance/trunk/config-dbcp.xml Thu Jul 26 23:10:54 2007 @@ -25,6 +25,8 @@ <url>jdbc:mysql:///test</url> <username></username> <password></password> + <!-- integerIndexed, integerScan, or textScan --> + <query-type>integerIndexed</query-type> </database> <connection-factory> @@ -68,9 +70,7 @@ </abandoned-config> <run> - <!-- integerIndexed, integerScan, or textScan --> - <query-type>integerIndexed</query-type> - <iterations>1000</iterations> + <iterations>100</iterations> <clients>50</clients> <delay-min>250</delay-min> <delay-max>500</delay-max> @@ -79,7 +79,9 @@ <delay-type>gaussian</delay-type> <!-- none, linear, random --> <ramp-type>random</ramp-type> - <period>20000</period> + <ramp-period>5000</ramp-period> + <peak-period>2000</peak-period> + <trough-period>5000</trough-period> <!-- none, oscillating (others?)--> <cycle-type>oscillating</cycle-type> </run> Modified: jakarta/commons/sandbox/performance/trunk/config-pool.xml URL: http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/trunk/config-pool.xml?view=diff&rev=560120&r1=560119&r2=560120 ============================================================================== --- jakarta/commons/sandbox/performance/trunk/config-pool.xml (original) +++ jakarta/commons/sandbox/performance/trunk/config-pool.xml Thu Jul 26 23:10:54 2007 @@ -66,7 +66,9 @@ <delay-type>gaussian</delay-type> <!-- none, linear, random --> <ramp-type>random</ramp-type> - <period>20000</period> + <ramp-period>5000</ramp-period> + <peak-period>2000</peak-period> + <trough-period>5000</trough-period> <!-- none, oscillating (others?)--> <cycle-type>oscillating</cycle-type> </run> Modified: jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/ClientThread.java URL: http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/ClientThread.java?view=diff&rev=560120&r1=560119&r2=560120 ============================================================================== --- jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/ClientThread.java (original) +++ jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/ClientThread.java Thu Jul 26 23:10:54 2007 @@ -44,8 +44,12 @@ protected double sigma; /** Delay type - determines how next start times are computed */ protected String delayType; - /** Period for cyclic mean delay */ - protected long period; + /** Ramp length for cyclic mean delay */ + protected long rampPeriod; + /** Peak length for cyclic mean delay */ + protected long peakPeriod; + /** Trough length for cyclic mean delay */ + protected long troughPeriod; /** Cycle type */ protected String cycleType; /** Ramp type */ @@ -62,8 +66,14 @@ protected double lastMean; /** Random data generator */ protected RandomData randomData; - /** Whether or now this thread is ramping up */ - protected boolean rampingUp = true; + + /** Cycle state constants */ + protected static final int RAMPING_UP = 0; + protected static final int RAMPING_DOWN = 1; + protected static final int PEAK_LOAD = 2; + protected static final int TROUGH_LOAD = 3; + /** Cycle state */ + protected int cycleState = 0; /** * Create a client thread. @@ -72,13 +82,16 @@ * @param minDelay minumum mean time between client requests * @param maxDelay maximum mean time between client requests * @param delayType distribution of time between client requests - * @param period period of cycle for cyclic load + * @param rampPeriod ramp period of cycle for cyclic load + * @param peakOeriod peak period of cycle for cyclic load + * @param troughPeriod trough period of cycle for cyclic load * @param cycleType type of cycle for mean delay * @param logger common logger shared by all clients * @param statsList List of SummaryStatistics to add results to */ public ClientThread(long iterations, long minDelay, long maxDelay, - double sigma, String delayType, long period, String cycleType, + double sigma, String delayType, long rampPeriod, long peakPeriod, + long troughPeriod, String cycleType, String rampType, Logger logger, List <SummaryStatistics> statsList) { this.iterations = iterations; @@ -86,7 +99,9 @@ this.maxDelay = maxDelay; this.sigma = sigma; this.delayType = delayType; - this.period = period; + this.peakPeriod = peakPeriod; + this.rampPeriod = rampPeriod; + this.troughPeriod = troughPeriod; this.cycleType = cycleType; this.rampType = rampType; this.logger = logger; @@ -207,11 +222,11 @@ double delayDifference = dMaxDelay - dMinDelay; if (cycleType.equals("none")) { if (rampType.equals("none") || - (currentTime - startTime) > period) { // ramped up + (currentTime - startTime) > rampPeriod) { // ramped up mean = dMinDelay; } else if (rampType.equals("linear")) { // single period linear double prop = - (double) (currentTime - startTime) / (double) period; + (double) (currentTime - startTime) / (double) rampPeriod; mean = dMaxDelay - delayDifference * prop; } else { // Random jumps down to delay - single period // TODO: govern size of jumps as in oscillating @@ -223,27 +238,22 @@ mean = dMaxDelay - delayDifference * prop; } } else if (cycleType.equals("oscillating")) { - // First check if we need to change directions - if ((currentTime - periodStart) >= period) { - if (rampingUp) { - rampingUp = false; - lastMean = dMinDelay; - } else { - rampingUp = true; - lastMean = dMaxDelay; - } - periodStart = currentTime; - } - if (rampType.equals("none")) { // minDelay or maxDelay, no ramp - if (rampingUp) { + // First change cycle state if we need to + adjustState(currentTime); + if (cycleState == PEAK_LOAD) { + mean = dMinDelay; + } else if (cycleState == TROUGH_LOAD) { + mean = dMaxDelay; + } else if (rampType.equals("none")) { // minDelay or maxDelay, no ramp + if (cycleState == RAMPING_UP) { mean = dMaxDelay; } else { mean = dMinDelay; } } else if (rampType.equals("linear")) { // ramp down, then up double prop = - (double)(currentTime - periodStart) / (double) period; - if (rampingUp) { + (double)(currentTime - periodStart) / (double) rampPeriod; + if (cycleState == RAMPING_UP) { mean = dMaxDelay - delayDifference * prop; } else { mean = dMinDelay + delayDifference * prop; @@ -254,20 +264,22 @@ (dMaxDelay - lastMean) / delayDifference; // Where we would be if this were a linear ramp double linearProp = - (double)(currentTime - periodStart) / (double) period; + (double)(currentTime - periodStart) / (double) rampPeriod; // Need to govern size of jumps, otherwise "convergence" // can be too fast - use linear ramp as governor - if ((rampingUp && (lastProp > linearProp)) || - (!rampingUp && ((1 - lastProp) > linearProp))) - lastProp = rampingUp ? linearProp : (1 - linearProp); + if ((cycleState == RAMPING_UP && (lastProp > linearProp)) || + (cycleState == RAMPING_DOWN && + ((1 - lastProp) > linearProp))) + lastProp = (cycleState == RAMPING_UP) ? linearProp : + (1 - linearProp); double prop = 0; - if (rampingUp) { // Random jump toward 1 + if (cycleState == RAMPING_UP) { // Random jump toward 1 prop = randomData.nextUniform(lastProp, 1); } else { // Random jump toward 0 prop = randomData.nextUniform(0, lastProp); } // Make sure sequence is monotone - if (rampingUp) { + if (cycleState == RAMPING_UP) { mean = Math.min(lastMean, maxDelay - delayDifference * prop); } else { @@ -287,5 +299,70 @@ return Math.round(randomData.nextPoisson(mean)); } } + } + + /** + * Adjusts cycleState, periodStart and lastMean if a cycle state + * transition needs to happen. + * + * @param currentTime current time + */ + protected void adjustState(long currentTime) { + switch (cycleState) { + case RAMPING_UP: { + if ((currentTime - periodStart) >= rampPeriod) { + if (peakPeriod > 0) { + cycleState = PEAK_LOAD; + } else { + cycleState = RAMPING_DOWN; + } + lastMean = (double) minDelay; + periodStart = currentTime; + } + break; + } + case RAMPING_DOWN: { + if ((currentTime - periodStart) >= rampPeriod) { + if (troughPeriod > 0) { + cycleState = TROUGH_LOAD; + } else { + cycleState = RAMPING_UP; + } + lastMean = (double) maxDelay; + periodStart = currentTime; + } + break; + } + case PEAK_LOAD: { + if ((currentTime - periodStart) >= peakPeriod) { + if (rampPeriod > 0) { + cycleState = RAMPING_DOWN; + lastMean = (double) minDelay; + } else { + cycleState = TROUGH_LOAD; + lastMean = (double) maxDelay; + } + periodStart = currentTime; + } + break; + } + case TROUGH_LOAD: { + if ((currentTime - periodStart) >= peakPeriod) { + if (rampPeriod > 0) { + cycleState = RAMPING_UP; + lastMean = (double) maxDelay; + } else { + cycleState = PEAK_LOAD; + lastMean = (double) minDelay; + } + periodStart = currentTime; + } + break; + } + default: { + throw new IllegalStateException( + "Illegal cycle state: " + cycleState); + } + } } } Added: jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/LoadGenerator.java URL: http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/LoadGenerator.java?view=auto&rev=560120 ============================================================================== --- jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/LoadGenerator.java (added) +++ jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/LoadGenerator.java Thu Jul 26 23:10:54 2007 @@ -0,0 +1,198 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.commons.performance; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; +import org.apache.commons.digester.Digester; +import org.apache.commons.math.random.RandomData; +import org.apache.commons.math.random.RandomDataImpl; +import org.apache.commons.math.stat.descriptive.SummaryStatistics; +import org.apache.commons.math.stat.descriptive.SummaryStatisticsImpl; +import org.apache.commons.performance.ConfigurationException; + +/** + * <p>Base class for load / peformance test runners. + * Uses Commons Digester to parse and load configuration and spawns + * ClientThread instances to generate load and gather statistics. + * </p> + * <p>Subclasses must implement [EMAIL PROTECTED] #makeClientThread()} to create client thread + * instances to be kicked off by execute.</p> + * <p> Sublasses may override [EMAIL PROTECTED] #configure()} to load additional configuration + * parameters and pass them on to the client in makeClientThread. + * </p> + * + */ +public abstract class LoadGenerator { + protected static Logger logger = Logger.getLogger(LoadGenerator.class.getName()); + private static List <SummaryStatistics> statsList = + new ArrayList <SummaryStatistics>(); + + // Client thread properties + protected long minDelay; + protected long maxDelay; + protected double sigma; + protected String delayType; + protected String rampType; + protected long rampPeriod; + protected long peakPeriod; + protected long troughPeriod; + protected String cycleType; + + // Run properties + private long numClients; + private long iterations; + + protected Digester digester = new Digester(); + protected String configFile = null; + + /** + * <p>Invokes [EMAIL PROTECTED] #configure()} to load digester rules, then digster.parse, + * then [EMAIL PROTECTED] #init()} to initialize configuration members. Then spawns and + * executes [EMAIL PROTECTED] #numClients} ClientThreads using [EMAIL PROTECTED] #makeClientThread} + * to create the ClientThread instances. + * </p> + * <p>Subclasses should not need to override this method, but must implement + * makeClientThread and may override configure and init to prepare data to + * pass to makeClientThread.</p> + * + * @throws Exception + */ + public void execute() throws Exception { + configure(); + digester.parse(configFile); + init(); + // Spawn and execute client threads + ExecutorService ex = Executors.newFixedThreadPool((int)numClients); + for (int i = 0; i < numClients; i++) { + ClientThread clientThread = makeClientThread(iterations, minDelay, + maxDelay, sigma, delayType, rampPeriod, peakPeriod, + troughPeriod, cycleType, rampType, logger, statsList); + ex.execute(clientThread); + } + ex.shutdown(); + // hard time limit of one day for now + // TODO: make this configurable + ex.awaitTermination(60 * 60 * 24, TimeUnit.SECONDS); + + // Compute summary statistics + SummaryStatistics meanSummary = new SummaryStatisticsImpl(); + SummaryStatistics stdSummary = new SummaryStatisticsImpl(); + SummaryStatistics minSummary = new SummaryStatisticsImpl(); + SummaryStatistics maxSummary = new SummaryStatisticsImpl(); + for (int i = 0; i < statsList.size(); i++) { + SummaryStatistics stats = (SummaryStatistics) statsList.get(i); + meanSummary.addValue(stats.getMean()); + stdSummary.addValue(stats.getStandardDeviation()); + minSummary.addValue(stats.getMin()); + maxSummary.addValue(stats.getMax()); + } + logger.info("Overall statistics for the mean"); + logger.info(meanSummary.toString()); + logger.info("Overall statistics for the standard deviation"); + logger.info(stdSummary.toString()); + logger.info("Overall statistics for the min"); + logger.info(minSummary.toString()); + logger.info("Overall statistics for the max"); + logger.info(maxSummary.toString()); + } + + protected abstract ClientThread makeClientThread( + long iterations, long minDelay, long maxDelay, double sigma, + String delayType, long rampPeriod, long peakPeriod, + long troughPeriod, String cycleType, String rampType, + Logger logger, List <SummaryStatistics> statsList); + + /** + * This method is invoked by [EMAIL PROTECTED] #execute()} after [EMAIL PROTECTED] #configure()} + * and digester parse, just before client threads are created. Objects that + * need to be created and passed to client threads using configuration info + * parsed from the config file should be created in this method. + * + * @throws Exception + */ + protected void init() throws Exception {} + + public void configureRun(String iterations, String clients, + String minDelay, String maxDelay, String sigma, + String delayType, String rampType, String rampPeriod, + String peakPeriod, String troughPeriod, String cycleType) + throws ConfigurationException { + + this.iterations = Long.parseLong(iterations); + this.numClients = Long.parseLong(clients); + this.minDelay = Long.parseLong(minDelay); + this.maxDelay = Long.parseLong(maxDelay); + this.sigma = Double.parseDouble(sigma); + this.delayType = delayType; + this.rampType = rampType; + this.rampPeriod = Long.parseLong(rampPeriod); + this.peakPeriod = Long.parseLong(peakPeriod); + this.troughPeriod = Long.parseLong(troughPeriod); + this.cycleType = cycleType; + if (cycleType.equals("oscillating") && this.rampPeriod <= 0) { + throw new ConfigurationException( + "Ramp period must be positive for oscillating cycle type"); + } + } + + /** + * <p>Starts preparing Digester to parse the configuration file, pushing + * *this onto the stack and loading rules to configure basic "run" + * parameters. + * </p> + * <p>Subclasses can override this, using super() to load base parameters + * and then adding additional addCallMethod sequences for additional parameters. + * </p> + * + * @throws Exception + */ + protected void configure() throws Exception { + digester.push(this); + + digester.addCallMethod("configuration/run", + "configureRun", 11); + digester.addCallParam( + "configuration/run/iterations", 0); + digester.addCallParam( + "configuration/run/clients", 1); + digester.addCallParam( + "configuration/run/delay-min", 2); + digester.addCallParam( + "configuration/run/delay-max", 3); + digester.addCallParam( + "configuration/run/delay-sigma", 4); + digester.addCallParam( + "configuration/run/delay-type", 5); + digester.addCallParam( + "configuration/run/ramp-type", 6); + digester.addCallParam( + "configuration/run/ramp-period", 7); + digester.addCallParam( + "configuration/run/peak-period", 8); + digester.addCallParam( + "configuration/run/trough-period", 9); + digester.addCallParam( + "configuration/run/cycle-type", 10); + + } +} Propchange: jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/LoadGenerator.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPClientThread.java URL: http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPClientThread.java?view=diff&rev=560120&r1=560119&r2=560120 ============================================================================== --- jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPClientThread.java (original) +++ jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPClientThread.java Thu Jul 26 23:10:54 2007 @@ -60,12 +60,14 @@ * @param statsList List of SummaryStatistics to add results to */ public DBCPClientThread(long iterations, long minDelay, long maxDelay, - double sigma, String delayType, String queryType, long period, - String cycleType, String rampType, Logger logger, - DataSource dataSource,List <SummaryStatistics> statsList) { + double sigma, String delayType, String queryType, long rampPeriod, + long peakPeriod, long troughPeriod, String cycleType, + String rampType, Logger logger, DataSource dataSource, + List <SummaryStatistics> statsList) { - super(iterations, minDelay, maxDelay, sigma, delayType, period, cycleType, - rampType, logger, statsList); + super(iterations, minDelay, maxDelay, sigma, delayType, rampPeriod, + peakPeriod, troughPeriod, cycleType, rampType, logger, + statsList); this.dataSource = dataSource; Modified: jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPSoak.java URL: http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPSoak.java?view=diff&rev=560120&r1=560119&r2=560120 ============================================================================== --- jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPSoak.java (original) +++ jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPSoak.java Thu Jul 26 23:10:54 2007 @@ -17,7 +17,7 @@ package org.apache.commons.performance.dbcp; -import org.apache.commons.performance.ConfigurationException; + import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; @@ -25,13 +25,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; import java.util.logging.Logger; - import javax.sql.DataSource; - import org.apache.commons.dbcp.AbandonedConfig; import org.apache.commons.dbcp.AbandonedObjectPool; import org.apache.commons.dbcp.ConnectionFactory; @@ -40,7 +35,6 @@ import org.apache.commons.dbcp.DriverManagerConnectionFactory; import org.apache.commons.dbcp.PoolableConnectionFactory; import org.apache.commons.dbcp.PoolingDataSource; -import org.apache.commons.digester.Digester; import org.apache.commons.pool.KeyedObjectPoolFactory; import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.impl.GenericKeyedObjectPool; @@ -49,7 +43,10 @@ import org.apache.commons.math.random.RandomData; import org.apache.commons.math.random.RandomDataImpl; import org.apache.commons.math.stat.descriptive.SummaryStatistics; -import org.apache.commons.math.stat.descriptive.SummaryStatisticsImpl; +import org.apache.commons.performance.ConfigurationException; +import org.apache.commons.performance.ClientThread; +import org.apache.commons.performance.LoadGenerator; +import org.apache.commons.performance.pool.WaiterFactory; /** * Configurable load / performance tester for commons dbcp. @@ -57,33 +54,18 @@ * DBCPClientThread instances to generate load and gather statistics. * */ -public class DBCPSoak { - private static Logger logger = Logger.getLogger(DBCPSoak.class.getName()); - private static List <SummaryStatistics> statsList = - new ArrayList <SummaryStatistics>(); +public class DBCPSoak extends LoadGenerator { + // Connection properties private String driverClass; private String connectUrl; private String connectUser; private String connectPassword; + private String queryType; + + // Connection pool properties private String poolType; private String driverType; private String factoryType; - private GenericObjectPool connectionPool; - private PoolingDataSource dataSource; - private long numClients; - private long iterations; - private int maxActive; - private int maxIdle; - private int minIdle; - private long maxWait; - private long minDelay; - private long maxDelay; - private double sigma; - private String delayType; - private String queryType; - private String rampType; - private long period; - private String cycleType; private boolean autocommit; private boolean readOnly; private byte exhaustedAction; @@ -97,8 +79,19 @@ private AbandonedConfig abandonedConfig = new AbandonedConfig(); private boolean poolPreparedStatements; private int maxOpenStatements; + private int maxActive; + private int maxIdle; + private int minIdle; + private long maxWait; - public void execute() throws Exception { + // Instance variables + private GenericObjectPool connectionPool; + private PoolingDataSource dataSource; + + /** + * Create connection pool and, if necessary, test table. + */ + protected void init() throws Exception { Class.forName(driverClass); // Create object pool @@ -178,49 +171,31 @@ } finally { conn.close(); } - - logger.info("Starting"); - - // Spawn and execute client threads - ExecutorService ex = Executors.newFixedThreadPool((int)numClients); - for (int i = 0; i < numClients; i++) { - ex.execute(new DBCPClientThread(iterations, minDelay, maxDelay, - sigma, delayType, queryType, period, cycleType, rampType, - logger, dataSource, statsList)); - } - ex.shutdown(); - // hard time limit of one day for now - // TODO: make this configurable - ex.awaitTermination(60 * 60 * 24, TimeUnit.SECONDS); - - // Compute summary statistics - SummaryStatistics meanSummary = new SummaryStatisticsImpl(); - SummaryStatistics stdSummary = new SummaryStatisticsImpl(); - SummaryStatistics minSummary = new SummaryStatisticsImpl(); - SummaryStatistics maxSummary = new SummaryStatisticsImpl(); - for (int i = 0; i < statsList.size(); i++) { - SummaryStatistics stats = (SummaryStatistics) statsList.get(i); - meanSummary.addValue(stats.getMean()); - stdSummary.addValue(stats.getStandardDeviation()); - minSummary.addValue(stats.getMin()); - maxSummary.addValue(stats.getMax()); - } - logger.info("Overall statistics for the mean"); - logger.info(meanSummary.toString()); - logger.info("Overall statistics for the standard deviation"); - logger.info(stdSummary.toString()); - logger.info("Overall statistics for the min"); - logger.info(minSummary.toString()); - logger.info("Overall statistics for the max"); - logger.info(maxSummary.toString()); - } + } + + protected ClientThread makeClientThread( + long iterations, long minDelay, long maxDelay, double sigma, + String delayType, long rampPeriod, long peakPeriod, + long troughPeriod, String cycleType, String rampType, + Logger logger, List <SummaryStatistics> statsList) { + + return new DBCPClientThread(iterations, minDelay, maxDelay, + sigma, delayType, queryType, rampPeriod, peakPeriod, + troughPeriod, cycleType, rampType, logger, dataSource, + statsList); + } + // ------------------------------------------------------------------------ + // Configuration methods specific to this LoadGenerator invoked by Digester + // when superclass execute calls digerster.parse. + // ------------------------------------------------------------------------ public void configureDataBase(String driver, String url, - String username, String password) { + String username, String password, String queryType) { this.driverClass = driver; this.connectUrl = url; this.connectUser = username; this.connectPassword = password; + this.queryType = queryType; } public void configureConnectionFactory(String type, @@ -264,7 +239,7 @@ throw new ConfigurationException( "Bad configuration setting for exhausted action: " + exhaustedAction); - } + } } public void configureAbandonedConfig(String logAbandoned, @@ -275,28 +250,7 @@ abandonedConfig.setRemoveAbandonedTimeout( Integer.parseInt(abandonedTimeout)); } - - public void configureRun(String queryType, String iterations, - String clients, String minDelay, String maxDelay, String sigma, - String delayType, String rampType, String period, String cycleType) - throws ConfigurationException { - this.queryType = queryType; - this.iterations = Long.parseLong(iterations); - this.numClients = Long.parseLong(clients); - this.minDelay = Long.parseLong(minDelay); - this.maxDelay = Long.parseLong(maxDelay); - this.sigma = Double.parseDouble(sigma); - this.delayType = delayType; - this.rampType = rampType; - this.period = Long.parseLong(period); - this.cycleType = cycleType; - if (cycleType.equals("oscillating") && this.period <= 0) { - throw new ConfigurationException( - "Period must be positive for oscillating cycle type"); - } - } - private void makeTable() throws Exception { Class.forName(driverClass); Connection db = DriverManager.getConnection(connectUrl,connectUser, @@ -326,16 +280,21 @@ } } - public void configure() throws Exception { - Digester digester = new Digester(); - digester.push(this); + /** + * Add dbcp configuration to parameters loaded by super. + * Also set config file name. + */ + protected void configure() throws Exception { + + super.configure(); digester.addCallMethod("configuration/database", - "configureDataBase", 4); + "configureDataBase", 5); digester.addCallParam("configuration/database/driver", 0); digester.addCallParam("configuration/database/url", 1); digester.addCallParam("configuration/database/username", 2); digester.addCallParam("configuration/database/password", 3); + digester.addCallParam("configuration/database/query-type", 4); digester.addCallMethod("configuration/connection-factory", "configureConnectionFactory", 4); @@ -384,29 +343,6 @@ digester.addCallParam( "configuration/pool/type", 11); - digester.addCallMethod("configuration/run", - "configureRun", 10); - digester.addCallParam( - "configuration/run/query-type", 0); - digester.addCallParam( - "configuration/run/iterations", 1); - digester.addCallParam( - "configuration/run/clients", 2); - digester.addCallParam( - "configuration/run/delay-min", 3); - digester.addCallParam( - "configuration/run/delay-max", 4); - digester.addCallParam( - "configuration/run/delay-sigma", 5); - digester.addCallParam( - "configuration/run/delay-type", 6); - digester.addCallParam( - "configuration/run/ramp-type", 7); - digester.addCallParam( - "configuration/run/period", 8); - digester.addCallParam( - "configuration/run/cycle-type", 9); - digester.addCallMethod("configuration/abandoned-config", "configureAbandonedConfig", 3); digester.addCallParam( @@ -416,7 +352,6 @@ digester.addCallParam( "configuration/abandoned-config/abandoned-timeout", 2); - digester.parse("config-dbcp.xml"); - + this.configFile = "config-dbcp.xml"; } } Modified: jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPTest.java URL: http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPTest.java?view=diff&rev=560120&r1=560119&r2=560120 ============================================================================== --- jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPTest.java (original) +++ jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPTest.java Thu Jul 26 23:10:54 2007 @@ -24,7 +24,6 @@ private static DBCPSoak soaker = new DBCPSoak(); public static void main(String[] args) { try { - soaker.configure(); soaker.execute(); } catch (Exception ex) { ex.printStackTrace(); Modified: jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolClientThread.java URL: http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolClientThread.java?view=diff&rev=560120&r1=560119&r2=560120 ============================================================================== --- jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolClientThread.java (original) +++ jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolClientThread.java Thu Jul 26 23:10:54 2007 @@ -41,18 +41,21 @@ * @param minDelay minumum mean time between client requests * @param maxDelay minumum mean time between client requests * @param delayType distribution of time between client requests - * @param period period of cycle for cyclic load + * @param rampPeriod ramp period of cycle for cyclic load + * @param peakOeriod peak period of cycle for cyclic load + * @param troughPeriod trough period of cycle for cyclic load * @param cycleType type of cycle for mean delay * @param logger common logger shared by all clients * @param statsList List of SummaryStatistics to add results to */ public PoolClientThread(long iterations, long minDelay, long maxDelay, - double sigma, String delayType, long period, - String cycleType, String rampType, Logger logger, + double sigma, String delayType, long rampPeriod, long peakPeriod, + long troughPeriod, String cycleType, String rampType, Logger logger, List <SummaryStatistics> statsList, ObjectPool pool) { - super(iterations, minDelay, maxDelay, sigma, delayType, period, cycleType, - rampType, logger, statsList); + super(iterations, minDelay, maxDelay, sigma, delayType, rampPeriod, + peakPeriod, troughPeriod, cycleType,rampType, logger, + statsList); this.pool = pool; } Modified: jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolSoak.java URL: http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolSoak.java?view=diff&rev=560120&r1=560119&r2=560120 ============================================================================== --- jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolSoak.java (original) +++ jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolSoak.java Thu Jul 26 23:10:54 2007 @@ -17,39 +17,20 @@ package org.apache.commons.performance.pool; -import org.apache.commons.performance.ConfigurationException; -import java.sql.Connection; -import java.sql.Driver; -import java.sql.DriverManager; -import java.sql.Statement; import java.util.ArrayList; import java.util.List; -import java.util.Properties; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; import java.util.logging.Logger; - -import javax.sql.DataSource; - import org.apache.commons.dbcp.AbandonedConfig; import org.apache.commons.dbcp.AbandonedObjectPool; -import org.apache.commons.dbcp.ConnectionFactory; -import org.apache.commons.dbcp.DataSourceConnectionFactory; -import org.apache.commons.dbcp.DriverConnectionFactory; -import org.apache.commons.dbcp.DriverManagerConnectionFactory; -import org.apache.commons.dbcp.PoolableConnectionFactory; -import org.apache.commons.dbcp.PoolingDataSource; -import org.apache.commons.digester.Digester; +import org.apache.commons.math.stat.descriptive.SummaryStatistics; import org.apache.commons.pool.KeyedObjectPoolFactory; import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.impl.GenericKeyedObjectPool; import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory; import org.apache.commons.pool.impl.GenericObjectPool; -import org.apache.commons.math.random.RandomData; -import org.apache.commons.math.random.RandomDataImpl; -import org.apache.commons.math.stat.descriptive.SummaryStatistics; -import org.apache.commons.math.stat.descriptive.SummaryStatisticsImpl; +import org.apache.commons.performance.ConfigurationException; +import org.apache.commons.performance.ClientThread; +import org.apache.commons.performance.LoadGenerator; /** * Configurable load / performance tester for commons pool. @@ -57,16 +38,11 @@ * PoolClientThread instances to generate load and gather statistics. * */ -public class PoolSoak { - private static Logger logger = Logger.getLogger(PoolSoak.class.getName()); - private static List <SummaryStatistics> statsList = - new ArrayList <SummaryStatistics>(); - +public class PoolSoak extends LoadGenerator { + // Pool properties private String poolType; private GenericObjectPool pool; - private long numClients; - private long iterations; private int maxActive; private int maxIdle; private int minIdle; @@ -80,15 +56,6 @@ private boolean testWhileIdle; private AbandonedConfig abandonedConfig = new AbandonedConfig(); - // Client thread properties - private long minDelay; - private long maxDelay; - private double sigma; - private String delayType; - private String rampType; - private long period; - private String cycleType; - // WaiterFactory properties private long activateLatency; private long destroyLatency; @@ -97,9 +64,69 @@ private long validateLatency; private long waiterLatency; + /** + * Add pool configuration to parameters loaded by super. + * Also set config file name. + */ + protected void configure() throws Exception { + super.configure(); + digester.addCallMethod("configuration/factory", + "configureFactory", 6); + digester.addCallParam( + "configuration/factory/activate-latency", 0); + digester.addCallParam( + "configuration/factory/destroy-latency", 1); + digester.addCallParam( + "configuration/factory/make-latency", 2); + digester.addCallParam( + "configuration/factory/passivate-latency", 3); + digester.addCallParam( + "configuration/factory/validate-latency", 4); + digester.addCallParam( + "configuration/factory/waiter-latency", 5); + digester.addCallMethod("configuration/pool", + "configurePool", 12); + digester.addCallParam( + "configuration/pool/max-active", 0); + digester.addCallParam( + "configuration/pool/max-idle", 1); + digester.addCallParam( + "configuration/pool/min-idle", 2); + digester.addCallParam( + "configuration/pool/max-wait", 3); + digester.addCallParam( + "configuration/pool/exhausted-action", 4); + digester.addCallParam( + "configuration/pool/test-on-borrow", 5); + digester.addCallParam( + "configuration/pool/test-on-return", 6); + digester.addCallParam( + "configuration/pool/time-between-evictions", 7); + digester.addCallParam( + "configuration/pool/tests-per-eviction", 8); + digester.addCallParam( + "configuration/pool/idle-timeout", 9); + digester.addCallParam( + "configuration/pool/test-while-idle", 10); + digester.addCallParam( + "configuration/pool/type", 11); + digester.addCallMethod("configuration/abandoned-config", + "configureAbandonedConfig", 3); + digester.addCallParam( + "configuration/abandoned-config/log-abandoned", 0); + digester.addCallParam( + "configuration/abandoned-config/remove-abandoned", 1); + digester.addCallParam( + "configuration/abandoned-config/abandoned-timeout", 2); + + this.configFile = "config-pool.xml"; + + } - public void execute() throws Exception { - + /** + * Create object pool and factory + */ + protected void init() throws Exception { // Create object pool if (poolType.equals("GenericObjectPool")) { pool = new GenericObjectPool( @@ -117,43 +144,25 @@ // Create factory pool.setFactory(new WaiterFactory(activateLatency, destroyLatency, makeLatency, passivateLatency, validateLatency, waiterLatency)); - - logger.info("Starting"); - - // Spawn and execute client threads - ExecutorService ex = Executors.newFixedThreadPool((int)numClients); - for (int i = 0; i < numClients; i++) { - ex.execute(new PoolClientThread(iterations, minDelay, maxDelay, - sigma, delayType, period, cycleType, rampType, - logger, statsList, pool)); - } - ex.shutdown(); - // hard time limit of one day for now - // TODO: make this configurable - ex.awaitTermination(60 * 60 * 24, TimeUnit.SECONDS); - - // Compute summary statistics - SummaryStatistics meanSummary = new SummaryStatisticsImpl(); - SummaryStatistics stdSummary = new SummaryStatisticsImpl(); - SummaryStatistics minSummary = new SummaryStatisticsImpl(); - SummaryStatistics maxSummary = new SummaryStatisticsImpl(); - for (int i = 0; i < statsList.size(); i++) { - SummaryStatistics stats = (SummaryStatistics) statsList.get(i); - meanSummary.addValue(stats.getMean()); - stdSummary.addValue(stats.getStandardDeviation()); - minSummary.addValue(stats.getMin()); - maxSummary.addValue(stats.getMax()); - } - logger.info("Overall statistics for the mean"); - logger.info(meanSummary.toString()); - logger.info("Overall statistics for the standard deviation"); - logger.info(stdSummary.toString()); - logger.info("Overall statistics for the min"); - logger.info(minSummary.toString()); - logger.info("Overall statistics for the max"); - logger.info(maxSummary.toString()); - } + } + /** + * Create and return a PoolClientThread + */ + protected ClientThread makeClientThread(long iterations, long minDelay, + long maxDelay, double sigma, String delayType, long rampPeriod, + long peakPeriod, long troughPeriod, String cycleType, + String rampType, Logger logger, + List <SummaryStatistics> statsList) { + return new PoolClientThread(iterations, minDelay, maxDelay, + sigma, delayType, rampPeriod, peakPeriod, troughPeriod, + cycleType, rampType, logger, statsList, pool); + } + + // ------------------------------------------------------------------------ + // Configuration methods specific to this LoadGenerator invoked by Digester + // when superclass execute calls digerster.parse. + // ------------------------------------------------------------------------ public void configureFactory(String activateLatency, String destroyLatency, String makeLatency, String passivateLatency, String validateLatency, String waiterLatency) { @@ -203,105 +212,4 @@ Integer.parseInt(abandonedTimeout)); } - public void configureRun(String queryType, String iterations, - String clients, String minDelay, String maxDelay, String sigma, - String delayType, String rampType, String period, String cycleType) - throws ConfigurationException { - - this.iterations = Long.parseLong(iterations); - this.numClients = Long.parseLong(clients); - this.minDelay = Long.parseLong(minDelay); - this.maxDelay = Long.parseLong(maxDelay); - this.sigma = Double.parseDouble(sigma); - this.delayType = delayType; - this.rampType = rampType; - this.period = Long.parseLong(period); - this.cycleType = cycleType; - if (cycleType.equals("oscillating") && this.period <= 0) { - throw new ConfigurationException( - "Period must be positive for oscillating cycle type"); - } - } - - public void configure() throws Exception { - Digester digester = new Digester(); - digester.push(this); - - digester.addCallMethod("configuration/factory", - "configureFactory", 6); - digester.addCallParam( - "configuration/factory/activate-latency", 0); - digester.addCallParam( - "configuration/factory/destroy-latency", 1); - digester.addCallParam( - "configuration/factory/make-latency", 2); - digester.addCallParam( - "configuration/factory/passivate-latency", 3); - digester.addCallParam( - "configuration/factory/validate-latency", 4); - digester.addCallParam( - "configuration/factory/waiter-latency", 5); - - digester.addCallMethod("configuration/pool", - "configurePool", 12); - digester.addCallParam( - "configuration/pool/max-active", 0); - digester.addCallParam( - "configuration/pool/max-idle", 1); - digester.addCallParam( - "configuration/pool/min-idle", 2); - digester.addCallParam( - "configuration/pool/max-wait", 3); - digester.addCallParam( - "configuration/pool/exhausted-action", 4); - digester.addCallParam( - "configuration/pool/test-on-borrow", 5); - digester.addCallParam( - "configuration/pool/test-on-return", 6); - digester.addCallParam( - "configuration/pool/time-between-evictions", 7); - digester.addCallParam( - "configuration/pool/tests-per-eviction", 8); - digester.addCallParam( - "configuration/pool/idle-timeout", 9); - digester.addCallParam( - "configuration/pool/test-while-idle", 10); - digester.addCallParam( - "configuration/pool/type", 11); - - digester.addCallMethod("configuration/run", - "configureRun", 10); - digester.addCallParam( - "configuration/run/query-type", 0); - digester.addCallParam( - "configuration/run/iterations", 1); - digester.addCallParam( - "configuration/run/clients", 2); - digester.addCallParam( - "configuration/run/delay-min", 3); - digester.addCallParam( - "configuration/run/delay-max", 4); - digester.addCallParam( - "configuration/run/delay-sigma", 5); - digester.addCallParam( - "configuration/run/delay-type", 6); - digester.addCallParam( - "configuration/run/ramp-type", 7); - digester.addCallParam( - "configuration/run/period", 8); - digester.addCallParam( - "configuration/run/cycle-type", 9); - - digester.addCallMethod("configuration/abandoned-config", - "configureAbandonedConfig", 3); - digester.addCallParam( - "configuration/abandoned-config/log-abandoned", 0); - digester.addCallParam( - "configuration/abandoned-config/remove-abandoned", 1); - digester.addCallParam( - "configuration/abandoned-config/abandoned-timeout", 2); - - digester.parse("config-pool.xml"); - - } } Modified: jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolTest.java URL: http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolTest.java?view=diff&rev=560120&r1=560119&r2=560120 ============================================================================== --- jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolTest.java (original) +++ jakarta/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/pool/PoolTest.java Thu Jul 26 23:10:54 2007 @@ -24,7 +24,6 @@ public static void main(String[] args) { PoolSoak soaker = new PoolSoak(); try { - soaker.configure(); soaker.execute(); } catch (Exception ex) { ex.printStackTrace(); --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]