Author: psteitz
Date: Mon Jul 16 23:11:36 2007
New Revision: 556823
URL: http://svn.apache.org/viewvc?view=rev&rev=556823
Log:
Initial Commit.
Added:
jakarta/commons/sandbox/performance/
jakarta/commons/sandbox/performance/build.properties
jakarta/commons/sandbox/performance/build.xml
jakarta/commons/sandbox/performance/config.xml
jakarta/commons/sandbox/performance/logging.properties
jakarta/commons/sandbox/performance/src/
jakarta/commons/sandbox/performance/src/java/
jakarta/commons/sandbox/performance/src/java/org/
jakarta/commons/sandbox/performance/src/java/org/apache/
jakarta/commons/sandbox/performance/src/java/org/apache/commons/
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/ClientThread.java
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/ConfigurationException.java
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPClientThread.java
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPSoak.java
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPTest.java
Added: jakarta/commons/sandbox/performance/build.properties
URL:
http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/build.properties?view=auto&rev=556823
==============================================================================
--- jakarta/commons/sandbox/performance/build.properties (added)
+++ jakarta/commons/sandbox/performance/build.properties Mon Jul 16 23:11:36
2007
@@ -0,0 +1,24 @@
+###############################################################################
+#
+# 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.
+###############################################################################
+
+# Remote maven repository
+mavenRepo=http://repo1.maven.org/maven2
+
+# JDBC driver
+jdbc-jar=/home/phil/mysql/mysql-connector-java-5.0.2.jar
+
Added: jakarta/commons/sandbox/performance/build.xml
URL:
http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/build.xml?view=auto&rev=556823
==============================================================================
--- jakarta/commons/sandbox/performance/build.xml (added)
+++ jakarta/commons/sandbox/performance/build.xml Mon Jul 16 23:11:36 2007
@@ -0,0 +1,124 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+
+<project name="DBCPTest" default="run" basedir=".">
+
+ <property name="src" location="src"/>
+ <property name="build" location="build"/>
+ <property name="lib" location="lib"/>
+
+ <property name="component-propfile" value="${basedir}/build.properties"/>
+ <property file="${component-propfile}"/>
+
+ <path id="compile.classpath">
+ <pathelement location="${jdbc-jar}"/>
+ <fileset dir="${lib}">
+ <include name="*.jar"/>
+ </fileset>
+ </path>
+
+ <path id="run.classpath">
+ <pathelement path="${build}"/>
+ <pathelement path="${java.class.path}"/>
+ <path refid="compile.classpath" />
+ </path>
+
+ <target name="init">
+ <mkdir dir="${build}"/>
+ <mkdir dir="${lib}"/>
+ </target>
+
+ <target name="get-collections">
+ <get
+
src="${mavenRepo}/commons-collections/commons-collections/3.1/commons-collections-3.1.jar"
+ dest="${lib}/commons-collections-3.1.jar"
+ usetimestamp="true"/>
+ </target>
+
+ <target name="get-beanutils">
+ <get
+
src="${mavenRepo}/commons-beanutils/commons-beanutils/1.6.1/commons-beanutils-1.6.1.jar"
+ dest="${lib}/commons-beanutils-1.6.1.jar"
+ usetimestamp="true"/>
+ </target>
+
+ <target name="get-digester">
+ <get
+
src="${mavenRepo}/commons-digester/commons-digester/1.4.1/commons-digester-1.4.1.jar"
+ dest="${lib}/commons-digester-1.4.1.jar"
+ usetimestamp="true"/>
+ </target>
+
+ <target name="get-math">
+ <get
+ src="${mavenRepo}/commons-math/commons-math/1.1/commons-math-1.1.jar"
+ dest="${lib}/commons-math-1.1.jar"
+ usetimestamp="true"/>
+ </target>
+
+ <target name="get-dbcp">
+ <get
+ src="${mavenRepo}/commons-dbcp/commons-dbcp/1.2.2/commons-dbcp-1.2.2.jar"
+ dest="${lib}/commons-dbcp-1.2.2.jar"
+ usetimestamp="true"/>
+ </target>
+
+ <target name="get-pool">
+ <get
+ src="${mavenRepo}/commons-pool/commons-pool/1.3/commons-pool-1.3.jar"
+ dest="${lib}/commons-pool-1.3.jar"
+ usetimestamp="true"/>
+ </target>
+
+ <target name="get-logging">
+ <get
+
src="${mavenRepo}/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar"
+ dest="${lib}/commons-logging-1.0.4.jar"
+ usetimestamp="true"/>
+ </target>
+
+ <target name="get-deps"
+
depends="get-collections,get-beanutils,get-digester,get-math,get-logging,get-dbcp,get-pool">
+ </target>
+
+ <target name="compile" depends="clean,init,get-deps">
+ <javac srcdir="${src}/java"
+ destdir="${build}">
+ <classpath refid="compile.classpath"/>
+ <compilerarg value="-Xlint:unchecked" />
+ </javac>
+ <copy file="${basedir}/config.xml" tofile="${build}/config.xml"/>
+ <copy file="${basedir}/logging.properties"
tofile="${build}/logging.properties"/>
+ </target>
+
+ <target name="run" depends="compile">
+ <java classname="org.apache.commons.performance.dbcp.DBCPTest" fork="true">
+ <classpath refid="run.classpath"/>
+ <jvmarg
+
value="-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger"/>
+ <jvmarg value="-Djava.util.logging.config.file=logging.properties"/>
+ </java>
+ </target>
+
+ <target name="clean">
+ <delete dir="${build}"/>
+ </target>
+</project>
Added: jakarta/commons/sandbox/performance/config.xml
URL:
http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/config.xml?view=auto&rev=556823
==============================================================================
--- jakarta/commons/sandbox/performance/config.xml (added)
+++ jakarta/commons/sandbox/performance/config.xml Mon Jul 16 23:11:36 2007
@@ -0,0 +1,86 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+
+<configuration>
+ <database>
+ <driver>com.mysql.jdbc.Driver</driver>
+ <url>jdbc:mysql:///test</url>
+ <username></username>
+ <password></password>
+ </database>
+
+ <connection-factory>
+ <!-- DriverManager or Driver -->
+ <type>DriverManager</type>
+ <auto-commit>true</auto-commit>
+ <read-only>false</read-only>
+ <!-- Validation query to use when testOnBorrow or testOnReturn is true -->
+ <validation-query></validation-query>
+ </connection-factory>
+
+ <poolable-connection-factory>
+ <!-- PoolableConnectionFactory or CPDSConnectionFactory (not yet) -->
+ <type>PoolableConnectionFactory</type>
+ <pool-prepared-statements>true</pool-prepared-statements>
+ <max-open-statements>-1</max-open-statements>
+ </poolable-connection-factory>
+
+ <pool>
+ <!-- GenericObjectPool or AbandonedObjectPool -->
+ <type>GenericObjectPool</type>
+ <max-active>15</max-active>
+ <max-idle>15</max-idle>
+ <min-idle>0</min-idle>
+ <max-wait>-1</max-wait>
+ <!-- block, fail, or grow -->
+ <exhausted-action>block</exhausted-action>
+ <test-on-borrow>false</test-on-borrow>
+ <test-on-return>false</test-on-return>
+ <time-between-evictions>-1</time-between-evictions>
+ <tests-per-eviction>3</tests-per-eviction>
+ <idle-timeout>-1</idle-timeout>
+ <test-while-idle>false</test-while-idle>
+ </pool>
+
+ <!-- Ignored unless pool type is AbandonedObjectPool -->
+ <abandoned-config>
+ <log-abandoned>true</log-abandoned>
+ <remove-abandoned>true</remove-abandoned>
+ <abandoned-timeout>50000</abandoned-timeout>
+ </abandoned-config>
+
+ <run>
+ <!-- integerIndexed, integerScan, or textScan -->
+ <query-type>integerIndexed</query-type>
+ <iterations>1000</iterations>
+ <clients>50</clients>
+ <delay-mean>250</delay-mean>
+ <delay-sigma>50</delay-sigma>
+ <!-- constant, gaussian, or poisson -->
+ <delay-type>gaussian</delay-type>
+ <!-- none, linear, random -->
+ <ramp-type>random</ramp-type>
+ <period>20000</period>
+ <!-- none, oscillating (others?)-->
+ <cycle-type>oscillating</cycle-type>
+ </run>
+
+</configuration>
Added: jakarta/commons/sandbox/performance/logging.properties
URL:
http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/logging.properties?view=auto&rev=556823
==============================================================================
--- jakarta/commons/sandbox/performance/logging.properties (added)
+++ jakarta/commons/sandbox/performance/logging.properties Mon Jul 16 23:11:36
2007
@@ -0,0 +1,38 @@
+###############################################################################
+#
+# 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.
+###############################################################################
+
+handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
+
+.level=WARNING
+
+org.apache.commons.pool.level=FINE
+org.apache.commons.dbcp.level=FINE
+org.apache.commons.performance.level=FINE
+
+java.util.logging.ConsoleHandler.level=SEVERE
+java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
+java.util.logging.FileHandler.level=FINE
+java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
+
+java.util.logging.FileHandler.pattern=%h/dbcpTest/dbcpSoak%u.log
+
+java.util.logging.FileHandler.limit=1000000
+
+java.util.logging.FileHandler.count=10
+
+
Added:
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/ClientThread.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/ClientThread.java?view=auto&rev=556823
==============================================================================
---
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/ClientThread.java
(added)
+++
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/ClientThread.java
Mon Jul 16 23:11:36 2007
@@ -0,0 +1,286 @@
+/*
+ * 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.List;
+import java.util.logging.Logger;
+
+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;
+
+/**
+ * Base for performance / load test clients.
+ * Run method executes init, then setup-execute-cleanup in a loop, gathering
+ * performance statistics, with time between executions determined by nextDelay
+ * method. See [EMAIL PROTECTED] for details on interarrival time computation.
+ *
+ */
+public abstract class ClientThread implements Runnable {
+
+ /** Number of iterations */
+ protected long iterations;
+ /** Mean time between requests */
+ protected long delay;
+ /** Standard deviation of delay distribution */
+ protected double sigma;
+ /** Delay type - determines how next start times are computed */
+ protected String delayType;
+ /** Period for cyclic mean delay */
+ protected long period;
+ /** Cycle type */
+ protected String cycleType;
+ /** Ramp type */
+ protected String rampType;
+ /** Logger shared by client threads */
+ protected Logger logger = null;
+ /** List of statistics to which to append stats for this client */
+ protected List <SummaryStatistics> statsList = null;
+ /** Start time of run */
+ protected long startTime;
+ /** Start time of current period */
+ protected long periodStart;
+ /** Last mean delay */
+ protected double lastMean;
+ /** Random data generator */
+ protected RandomData randomData;
+ /** Whether or now this thread is ramping up */
+ protected boolean rampingUp = true;
+
+ /**
+ * Create a client thread.
+ *
+ * @param iterations number of iterations
+ * @param delay mean time between client requests
+ * @param delayType distribution of time between client requests
+ * @param period 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 delay, double sigma,
+ String delayType, long period, String cycleType,
+ String rampType, Logger logger,
+ List <SummaryStatistics> statsList) {
+ this.iterations = iterations;
+ this.delay = delay;
+ this.sigma = sigma;
+ this.delayType = delayType;
+ this.period = period;
+ this.cycleType = cycleType;
+ this.rampType = rampType;
+ this.logger = logger;
+ this.statsList = statsList;
+ }
+
+ public void run() {
+ try {
+ init();
+ } catch (Exception ex) {
+ logger.severe("init failed.");
+ ex.printStackTrace();
+ return;
+ }
+ long start = 0;
+ startTime = System.currentTimeMillis();
+ long lastStart = startTime;
+ long numMisses = 0;
+ long numErrors = 0;
+ SummaryStatistics stats = new SummaryStatisticsImpl();
+ randomData = new RandomDataImpl();
+ periodStart = System.currentTimeMillis();
+ lastMean = (double) (2 * delay); // Ramp up, if any, starts here
+ for (int i = 0; i < iterations; i++) {
+ try {
+ setup();
+ // Generate next interarrival time. If that is in the
+ // past, go right away and log a miss; otherwise wait.
+ long elapsed = System.currentTimeMillis() - lastStart;
+ long nextDelay = nextDelay();
+ if (elapsed > nextDelay) {
+ numMisses++;
+ } else {
+ try {
+ Thread.sleep(nextDelay - elapsed);
+ } catch (InterruptedException ex) {
+ logger.info("Sleep interrupted");
+ }
+ }
+
+ // Fire the request and measure response time
+ start = System.currentTimeMillis();
+ execute();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ numErrors++;
+ } finally {
+ try {
+ stats.addValue(System.currentTimeMillis() - start);
+ lastStart = start;
+ cleanUp();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // Report statistics
+ logger.info(stats.toString() +
+ "Number of misses: " + numMisses + "\n" +
+ "Number or errors: " + numErrors + "\n");
+ statsList.add(stats);
+ }
+
+ /** Executed once at the beginning of the run */
+ protected void init() throws Exception {}
+
+ /** Executed at the beginning of each iteration */
+ protected void setup() throws Exception {}
+
+ /** Executed in finally block of iteration try-catch */
+ protected void cleanUp() throws Exception {}
+
+ /** Core iteration code. Timings are based on this,
+ * so keep it tight.
+ * */
+ public abstract void execute() throws Exception;
+
+ /**
+ * <p>Computes the next interarrival time (time to wait between requests)
+ * based on configured values for mean delay, delay type, cycle type,
+ * ramp type and period.
+ * </p>
+ * <p>Currently supports constant (just returning mean delay time), Poisson
+ * and Gaussian distributed random time delays, linear and random ramps,
+ * and oscillating / non-oscillating cycle types.
+ * </p>
+ * <p>If delayType = "constant" the configured delay mean is always
returned.
+ * If delayType is "gaussian" or "exponential" and cycleType is "none",
+ * random deviates with the configured parameters are returned.
+ * </p>
+ * <p>If delayType is not "constant" and cycleType is "oscillating", means
+ * of random deviates ramp up and down between delay and twice delay. Ramp
+ * type is controlled by rampType. Linear rampType means the means
+ * increase or decrease linearly over the time of the period. Random
+ * makes random jumps up or down toward the next peak or trough. "None" for
+ * rampType under oscillating cycleType makes the means alternate bttween
+ * peak (delay) and trough (twice delay) with no ramp between.
+ * </p>
+ * <p>For non-oscillating, non-constant runs, linear and random rampTypes
+ * work similarly, but over just one ramp up period at the beginning of
+ * the run.
+ * </p>
+ *
+ * @param currentTime current time
+ * @return next value for delay
+ */
+ protected long nextDelay() {
+ long currentTime = System.currentTimeMillis();
+ double mean = 0;
+ if (delayType.equals("constant")) {
+ //TODO: should support single ramp up to constant
+ return delay;
+ } else { // delay not constant, use random variate
+
+ // Determine mean to use
+ double doubleDelay = (double) delay;
+ double top = 2d * doubleDelay; // delay is peak, ramp starts at top
+ if (cycleType.equals("none")) {
+ if (rampType.equals("none") ||
+ (currentTime - startTime) > period) {
+ // use configured mean
+ mean = doubleDelay;
+ } else if (rampType.equals("linear")) { // single period linear
+ double prop = (double) (currentTime - startTime) / period ;
+ mean = top - doubleDelay * prop;
+ } else { // Random jumps down to delay - single period
+ // Where we last were as proportion of way down to delay
+ double lastProp =
+ (top - lastMean) / doubleDelay;
+ // Make a random jump toward 1 (1 = all the way down)
+ double prop = randomData.nextUniform(lastProp, 1);
+ mean = top - doubleDelay * prop;
+ }
+ } else if (cycleType.equals("oscillating")) {
+ // First check if we need to change directions
+ if ((currentTime - periodStart) >= period) {
+ if (rampingUp) {
+ rampingUp = false;
+ lastMean = doubleDelay;
+ } else {
+ rampingUp = true;
+ lastMean = top;
+ }
+ periodStart = currentTime;
+ }
+ if (rampType.equals("none")) { // mean or twice mean, no ramp
+ if (rampingUp) {
+ mean = top;
+ } else {
+ mean = doubleDelay;
+ }
+ } else if (rampType.equals("linear")) { // ramp down, then up
+ double prop =
+ (double)(currentTime - periodStart) / (double) period;
+ if (rampingUp) {
+ mean = top - doubleDelay * prop;
+ } else {
+ mean = doubleDelay + doubleDelay * prop;
+ }
+ } else { // random jumps down, then back up
+ // Where we last were as proportion of way down to delay
+ double lastProp =
+ (top - lastMean) / doubleDelay;
+ // Where we would be if this were a linear ramp
+ double linearProp =
+ (double)(currentTime - periodStart) / (double) period;
+ // Need to govern size of jumps, otherwise "convergence"
+ // can be too fast - use linear ramp as governor
+ if ((rampingUp && (lastProp > linearProp)) ||
+ (!rampingUp && (lastProp < linearProp))) { // Slow down
+ lastProp = linearProp;
+ }
+ double prop = 0;
+ if (rampingUp) { // 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) {
+ mean = Math.min(lastMean, top - doubleDelay * prop);
+ } else {
+ mean = Math.max(lastMean, top - doubleDelay * prop);
+ }
+ }
+ }
+
+ // Remember last mean for ramp up / down
+ lastMean = mean;
+
+ // Generate and return random deviate
+ if (delayType.equals("gaussian")) {
+ return Math.round(randomData.nextGaussian(mean, sigma));
+ } else { // must be Poisson
+ return Math.round(randomData.nextPoisson(mean));
+ }
+ }
+ }
+
+}
Added:
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/ConfigurationException.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/ConfigurationException.java?view=auto&rev=556823
==============================================================================
---
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/ConfigurationException.java
(added)
+++
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/ConfigurationException.java
Mon Jul 16 23:11:36 2007
@@ -0,0 +1,37 @@
+/*
+ * 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.dbcp;
+
+public class ConfigurationException extends Exception {
+
+ public ConfigurationException() {
+ super();
+ }
+
+ public ConfigurationException(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+ }
+
+ public ConfigurationException(String arg0) {
+ super(arg0);
+ }
+
+ public ConfigurationException(Throwable arg0) {
+ super(arg0);
+ }
+
+}
Added:
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPClientThread.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPClientThread.java?view=auto&rev=556823
==============================================================================
---
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPClientThread.java
(added)
+++
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPClientThread.java
Mon Jul 16 23:11:36 2007
@@ -0,0 +1,111 @@
+/*
+ * 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.dbcp;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.List;
+import java.util.logging.Logger;
+import javax.sql.DataSource;
+
+import org.apache.commons.math.stat.descriptive.SummaryStatistics;
+import org.apache.commons.performance.ClientThread;
+
+/**
+ * Client thread that executes requests in a loop using a configured
DataSource,
+ * with number of requests, time between requests and query strings governed by
+ * constructor parameters. See ClientThread javadoc for a description
+ * of how times between requests are computed.
+ *
+ */
+public class DBCPClientThread extends ClientThread {
+ /** Initial segment of query string */
+ private String queryString;
+ /** Whether or not the query is on the text column */
+ private boolean textQuery = false;
+ /** DataSource used to connect */
+ private DataSource dataSource = null;
+ /** Database connection */
+ Connection conn = null;
+ /** Current query */
+ String currentQuery = null;
+
+ /**
+ * Create a dbcp client thread.
+ *
+ * @param iterations number of iterations
+ * @param delay mean time between client requests
+ * @param delayType distribution of time between client requests
+ * @param queryType type of query
+ * @param period period of cycle for cyclic load
+ * @param cycleType type of cycle for mean delay
+ * @param logger common logger shared by all clients
+ * @param dataSource DataSource for connections
+ * @param statsList List of SummaryStatistics to add results to
+ */
+ public DBCPClientThread(long iterations, long delay, double sigma,
+ String delayType, String queryType, long period, String cycleType,
+ String rampType, Logger logger, DataSource dataSource,
+ List <SummaryStatistics> statsList) {
+
+ super(iterations, delay, sigma, delayType, period, cycleType,
+ rampType, logger, statsList);
+
+ this.dataSource = dataSource;
+
+ if (queryType.equals("integerIndexed")) {
+ queryString = "select * from test_table WHERE indexed=";
+ } else if (queryType.equals("integerScan")) {
+ queryString = "select * from test_table WHERE not_indexed=";
+ } else {
+ queryString = "select * from test_table WHERE text='";
+ textQuery = true;
+ }
+ }
+
+ /** Generate a random query */
+ public void setup() throws Exception {
+ if (textQuery) {
+ currentQuery = queryString +
+ randomData.nextHexString(20) + "';";
+ } else {
+ currentQuery = queryString +
+ randomData.nextInt(0, 100) + ";";
+ }
+ }
+
+ /** Execute query */
+ public void execute() throws Exception {
+ conn = dataSource.getConnection();
+ Statement stmt = conn.createStatement();
+ stmt.execute(currentQuery);
+ ResultSet rs = stmt.getResultSet();
+ if (!rs.isAfterLast()) {
+ rs.next();
+ }
+ rs.close();
+ stmt.close();
+ }
+
+ /** Close connection */
+ public void cleanUp() throws Exception {
+ conn.close();
+ }
+
+}
Added:
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPSoak.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPSoak.java?view=auto&rev=556823
==============================================================================
---
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPSoak.java
(added)
+++
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPSoak.java
Mon Jul 16 23:11:36 2007
@@ -0,0 +1,415 @@
+/*
+ * 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.dbcp;
+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.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;
+
+/**
+ * Configurable load / performance tester for commons dbcp.
+ * Uses Commons Digester to parse and load configuration and spawns
+ * 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>();
+ private String driverClass;
+ private String connectUrl;
+ private String connectUser;
+ private String connectPassword;
+ 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 delay;
+ 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;
+ private boolean testOnBorrow;
+ private boolean testOnReturn;
+ private long timeBetweenEvictions;
+ private int testsPerEviction;
+ private long idleTimeout;
+ private boolean testWhileIdle;
+ private String validationQuery;
+ private AbandonedConfig abandonedConfig = new AbandonedConfig();
+ private boolean poolPreparedStatements;
+ private int maxOpenStatements;
+
+ public void execute() throws Exception {
+ Class.forName(driverClass);
+
+ // Create object pool
+ if (poolType.equals("GenericObjectPool")) {
+ connectionPool = new GenericObjectPool(
+ null, maxActive, exhaustedAction,
+ maxWait, maxIdle, minIdle, testOnBorrow, testOnReturn,
+ timeBetweenEvictions, testsPerEviction, idleTimeout,
+ testWhileIdle);
+ } else if (poolType.equals("AbandonedObjectPool")) {
+ connectionPool = new AbandonedObjectPool(null,abandonedConfig);
+ } else {
+ throw new ConfigurationException(
+ "invalid pool type configuration: " + poolType);
+ }
+
+ // Create raw connection factory
+ ConnectionFactory connectionFactory = null;
+ if (driverType.equals("DriverManager")) {
+ connectionFactory = new DriverManagerConnectionFactory(
+ connectUrl,connectUser,
+ connectPassword);
+ } else if (driverType.equals("Driver")) {
+ Properties props = new Properties();
+ props.put("user", connectUser);
+ props.put("password", connectPassword);
+ connectionFactory = new DriverConnectionFactory(
+ (Driver) Class.forName(driverClass).newInstance(),
+ connectUrl, props);
+ } else {
+ throw new ConfigurationException(
+ "Bad config setting for driver type");
+ }
+
+ // Create object factory
+ PoolableObjectFactory poolableConnectionFactory = null;
+ KeyedObjectPoolFactory statementPoolFactory = null;
+ if (poolPreparedStatements) { // Use same defaults as BasicDataSource
+ statementPoolFactory = new GenericKeyedObjectPoolFactory(null,
+ -1, // unlimited maxActive (per key)
+ GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,
+ 0, // maxWait
+ 1, // maxIdle (per key)
+ maxOpenStatements); //TODO: make all configurable
+ }
+ if (factoryType.equals("PoolableConnectionFactory")) {
+ poolableConnectionFactory =
+ new PoolableConnectionFactory(
+ connectionFactory,connectionPool, statementPoolFactory,
+ validationQuery, readOnly, autocommit);
+ } else if (factoryType.equals("CPDSConnectionFactory")) {
+ throw new ConfigurationException(
+ "CPDSConnectionFactory not implemented yet");
+ } else {
+ throw new ConfigurationException(
+ "Invalid factory type: " + factoryType);
+ }
+
+ // Create DataSource
+ dataSource = new PoolingDataSource(connectionPool);
+
+ // Try to connect and query test_table. If "test_table" appears in
+ // exception message, assume table needs to be created.
+ Connection conn = dataSource.getConnection();
+ try {
+ Statement stmnt = conn.createStatement();
+ stmnt.execute("select * from test_table where indexed=1;");
+ stmnt.close();
+ } catch (Exception ex) {
+ if (ex.getMessage().indexOf("test_table") > 0) {
+ logger.info("Creating test_table");
+ makeTable();
+ logger.info("test_table created successfully");
+ } else {
+ throw ex;
+ }
+ } 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, delay,
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());
+ }
+
+ public void configureDataBase(String driver, String url,
+ String username, String password) {
+ this.driverClass = driver;
+ this.connectUrl = url;
+ this.connectUser = username;
+ this.connectPassword = password;
+ }
+
+ public void configureConnectionFactory(String type,
+ String autoCommit, String readOnly, String validationQuery) {
+ this.driverType = type;
+ this.autocommit = Boolean.parseBoolean(autoCommit);
+ this.readOnly = Boolean.parseBoolean(readOnly);
+ this.validationQuery = validationQuery;
+ }
+
+ public void configurePoolableConnectionFactory(String type,
+ String poolPreparedStatements, String maxOpenStatements) {
+ this.factoryType = type;
+ this.poolPreparedStatements =
+ Boolean.parseBoolean(poolPreparedStatements);
+ this.maxOpenStatements = Integer.parseInt(maxOpenStatements);
+ }
+
+ public void configurePool(String maxActive, String maxIdle, String minIdle,
+ String maxWait, String exhaustedAction, String testOnBorrow,
+ String testOnReturn, String timeBetweenEvictions,
+ String testsPerEviction, String idleTimeout,
+ String testWhileIdle, String type) throws ConfigurationException {
+ this.maxActive = Integer.parseInt(maxActive);
+ this.maxIdle = Integer.parseInt(maxIdle);
+ this.maxWait = Long.parseLong(maxWait);
+ this.testOnBorrow = Boolean.parseBoolean(testOnBorrow);
+ this.testOnReturn = Boolean.parseBoolean(testOnReturn);
+ this.timeBetweenEvictions = Long.parseLong(timeBetweenEvictions);
+ this.testsPerEviction = Integer.parseInt(testsPerEviction);
+ this.idleTimeout = Long.parseLong(idleTimeout);
+ this.testWhileIdle = Boolean.parseBoolean(testWhileIdle);
+ this.poolType = type;
+ if (exhaustedAction.equals("block")) {
+ this.exhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;
+ } else if (exhaustedAction.equals("fail")) {
+ this.exhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_FAIL;
+ } else if (exhaustedAction.equals("grow")) {
+ this.exhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
+ } else {
+ throw new ConfigurationException(
+ "Bad configuration setting for exhausted action: "
+ + exhaustedAction);
+ }
+ }
+
+ public void configureAbandonedConfig(String logAbandoned,
+ String removeAbandoned, String abandonedTimeout) {
+ abandonedConfig.setLogAbandoned(Boolean.parseBoolean(logAbandoned));
+ abandonedConfig.setRemoveAbandoned(
+ Boolean.parseBoolean(removeAbandoned));
+ abandonedConfig.setRemoveAbandonedTimeout(
+ Integer.parseInt(abandonedTimeout));
+ }
+
+ public void configureRun(String queryType, String iterations,
+ String clients, String delay, 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.delay = Long.parseLong(delay);
+ 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,
+ connectPassword);
+ try {
+ Statement sql = db.createStatement();
+ String sqlText =
+ "create table test_table (indexed int, text varchar(20)," +
+ " not_indexed int)";
+ sql.executeUpdate(sqlText);
+ sqlText = "CREATE INDEX test1_id_index ON test_table (indexed);";
+ sql.executeUpdate(sqlText);
+ RandomData randomData = new RandomDataImpl();
+ for (int i = 0; i < 10000; i++) {
+ int indexed = randomData.nextInt(0, 100);
+ int not_indexed = randomData.nextInt(0, 1000);
+ String text = randomData.nextHexString(20);
+ sqlText =
+ "INSERT INTO test_table (indexed, text, not_indexed)" +
+ "VALUES (" + indexed + "," + "'"+ text + "'," +
+ not_indexed + ");";
+ sql.executeUpdate(sqlText);
+ }
+ sql.close();
+ } finally {
+ db.close();
+ }
+ }
+
+ public void configure() throws Exception {
+ Digester digester = new Digester();
+ digester.push(this);
+
+ digester.addCallMethod("configuration/database",
+ "configureDataBase", 4);
+ 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.addCallMethod("configuration/connection-factory",
+ "configureConnectionFactory", 4);
+ digester.addCallParam(
+ "configuration/connection-factory/type", 0);
+ digester.addCallParam(
+ "configuration/connection-factory/auto-commit", 1);
+ digester.addCallParam(
+ "configuration/connection-factory/read-only", 2);
+ digester.addCallParam(
+ "configuration/connection-factory/validation-query", 3);
+
+ digester.addCallMethod("configuration/poolable-connection-factory",
+ "configurePoolableConnectionFactory", 3);
+ digester.addCallParam(
+ "configuration/poolable-connection-factory/type", 0);
+ digester.addCallParam(
+
"configuration/poolable-connection-factory/pool-prepared-statements", 1);
+ digester.addCallParam(
+
"configuration/poolable-connection-factory/max-open-statements", 2);
+
+ 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", 9);
+ digester.addCallParam(
+ "configuration/run/query-type", 0);
+ digester.addCallParam(
+ "configuration/run/iterations", 1);
+ digester.addCallParam(
+ "configuration/run/clients", 2);
+ digester.addCallParam(
+ "configuration/run/delay-mean", 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/period", 7);
+ digester.addCallParam(
+ "configuration/run/cycle-type", 8);
+
+ 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("/home/phil/dbcpTest/config.xml");
+
+ }
+}
Added:
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPTest.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPTest.java?view=auto&rev=556823
==============================================================================
---
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPTest.java
(added)
+++
jakarta/commons/sandbox/performance/src/java/org/apache/commons/performance/dbcp/DBCPTest.java
Mon Jul 16 23:11:36 2007
@@ -0,0 +1,33 @@
+/*
+ * 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.dbcp;
+
+/**
+ * Load / performance test runner.
+ *
+ */
+public class DBCPTest {
+ private static DBCPSoak soaker = new DBCPSoak();
+ public static void main(String[] args) {
+ try {
+ soaker.configure();
+ soaker.execute();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]