You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2008/02/07 14:25:27 UTC
svn commit: r619404 - in
/db/derby/code/trunk/java/testing/org/apache/derbyTesting:
functionTests/tests/lang/ perf/clients/
Author: kahatlen
Date: Thu Feb 7 05:25:24 2008
New Revision: 619404
URL: http://svn.apache.org/viewvc?rev=619404&view=rev
Log:
Checked in the performance tests used in DERBY-1961 and DERBY-2911.
The following command prints information on how to run the tests:
java org.apache.derbyTesting.perf.clients.Runner
Added:
db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/
db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/DBFiller.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/LoadGenerator.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordFiller.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/WisconsinFiller.java (with props)
Modified:
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/wisconsin.java
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/wisconsin.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/wisconsin.java?rev=619404&r1=619403&r2=619404&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/wisconsin.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/wisconsin.java Thu Feb 7 05:25:24 2008
@@ -40,7 +40,7 @@
conn.setAutoCommit(false);
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
- createTables(conn);
+ createTables(conn, true);
BufferedInputStream inStream;
@@ -62,7 +62,9 @@
conn.commit();
}
- private static void createTables(Connection conn) throws SQLException{
+ public static void createTables(Connection conn, boolean compress)
+ throws SQLException {
+
Statement stmt = conn.createStatement();
stmt.execute("create table TENKTUP1 ( unique1 int not null, " +
@@ -166,7 +168,11 @@
stmt.execute("insert into BPRIME select * from TENKTUP2 where TENKTUP2.unique2 < 1000");
conn.commit();
-
+
+ if (!compress) {
+ return;
+ }
+
PreparedStatement ps2 = conn.prepareStatement
("call SYSCS_UTIL.SYSCS_COMPRESS_TABLE(?, ?, ?)");
ps2.setString(1, "APP");
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java Thu Feb 7 05:25:24 2008
@@ -0,0 +1,132 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.BackToBackLoadGenerator
+
+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.derbyTesting.perf.clients;
+
+import java.io.PrintStream;
+import java.sql.SQLException;
+
+/**
+ * Load generator which creates back-to-back load. This means that you have a
+ * number of threads running in parallel, where each thread continuously
+ * performs operations with no pauses in between.
+ */
+public class BackToBackLoadGenerator implements LoadGenerator {
+ /** The threads executing. */
+ private ClientThread[] threads;
+ /** Flag which tells the generator to stop. */
+ private volatile boolean stop;
+ /** Flag which tells the generator to collect results. */
+ private volatile boolean collect;
+ /** Start time for steady-state phase. */
+ private long startTime;
+ /** Stop time for steady-state phase. */
+ private long stopTime;
+
+ /**
+ * Thread class which runs a single client and collects results.
+ */
+ private class ClientThread extends Thread {
+ private final Client client;
+ private long count;
+
+ ClientThread(Client c) {
+ client = c;
+ }
+
+ public void run() {
+ try {
+ while (!stop) {
+ client.doWork();
+ if (collect) {
+ count++;
+ }
+ }
+ } catch (SQLException sqle) {
+ sqle.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Initialize the load generator.
+ *
+ * @param clients the test clients to use
+ */
+ public void init(Client[] clients) {
+ threads = new ClientThread[clients.length];
+ for (int i = 0; i < clients.length; i++) {
+ threads[i] = new ClientThread(clients[i]);
+ }
+ }
+
+ /**
+ * Start warmup.
+ */
+ public void startWarmup() {
+ for (int i = 0; i < threads.length; i++) {
+ threads[i].start();
+ }
+ }
+
+ /**
+ * Start steady state.
+ */
+ public void startSteadyState() {
+ startTime = System.currentTimeMillis();
+ collect = true;
+ }
+
+ /**
+ * Stop the load generator.
+ */
+ public void stop() {
+ stopTime = System.currentTimeMillis();
+ collect = false;
+ stop = true;
+ for (int i = 0; i < threads.length; i++) {
+ try {
+ threads[i].join();
+ } catch (InterruptedException ie) {
+ ie.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Print average number of transactions per second.
+ */
+ public void printReport(PrintStream out) {
+ long time = stopTime - startTime;
+
+ long count = 0;
+ for (int i = 0; i < threads.length; i++) {
+ count += threads[i].count;
+ }
+
+ double tps = (double) count * 1000 / time;
+
+ out.println("Number of threads:\t" + threads.length);
+ out.println("Test duration (s):\t" + ((double) time / 1000));
+ out.println("Number of transactions:\t" + count);
+ out.println("Average throughput (tx/s):\t" + tps);
+ }
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java Thu Feb 7 05:25:24 2008
@@ -0,0 +1,50 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.Client
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * Interface that must be implemented by performance clients. The
+ * implementations of this interface normally perform a single operation, and
+ * the selected implementation of {@code LoadGenerator} repeatedly invokes this
+ * operation in order to get the desired distribution.
+ */
+public interface Client {
+ /**
+ * Initialize this client (typically prepare the statements needed in the
+ * {@code doWork()} method).
+ *
+ * @param c a connection which can be used by this client
+ * @throws SQLException if a database error occurs
+ */
+ void init(Connection c) throws SQLException;
+
+ /**
+ * Perform the work for a single iteration of the test (typically a single
+ * transaction).
+ *
+ * @throws SQLException if a database error occurs
+ */
+ void doWork() throws SQLException;
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/DBFiller.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/DBFiller.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/DBFiller.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/DBFiller.java Thu Feb 7 05:25:24 2008
@@ -0,0 +1,38 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.DBFiller
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * Interface for classes that populate a database for a certain test.
+ */
+public interface DBFiller {
+ /**
+ * Populate the database with the data needed by a test.
+ *
+ * @param c the connection to use
+ * @throws SQLException if a database error occurs
+ */
+ void fill(Connection c) throws SQLException;
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/DBFiller.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java Thu Feb 7 05:25:24 2008
@@ -0,0 +1,55 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.IndexJoinClient
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.ResultSet;
+
+/**
+ * Test client which performs an index join between the {@code TENKTUP1} and
+ * {@code ONEKTUP} tables generated by {@code WisconsinFiller}.
+ */
+public class IndexJoinClient implements Client {
+
+ private Connection conn;
+ private PreparedStatement ps;
+
+ public void init(Connection c) throws SQLException {
+ conn = c;
+ ps = c.prepareStatement(
+ "SELECT TENKTUP1.UNIQUE1 FROM TENKTUP1, ONEKTUP WHERE " +
+ "TENKTUP1.UNIQUE1 = ONEKTUP.UNIQUE1");
+ c.setAutoCommit(false);
+ }
+
+ public void doWork() throws SQLException {
+ ResultSet rs = ps.executeQuery();
+ while (rs.next()) {
+ rs.getInt(1);
+ }
+ rs.close();
+ conn.commit();
+ }
+
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/LoadGenerator.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/LoadGenerator.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/LoadGenerator.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/LoadGenerator.java Thu Feb 7 05:25:24 2008
@@ -0,0 +1,64 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.LoadGenerator
+
+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.derbyTesting.perf.clients;
+
+import java.io.PrintStream;
+
+/**
+ * Interface implemented by load generators. A load generator generates the
+ * test load on the DBMS by invoking the clients' {@code doWork()} methods.
+ * Different load generators may generate load with different characteristics.
+ * The actual database operations performed are decided by the clients passed
+ * in to the load generator's {@code init()} method.
+ */
+public interface LoadGenerator {
+ /**
+ * Initialize the load generator.
+ * @param clients tells the load generator which clients it should use
+ * to generate load with
+ */
+ void init(Client[] clients);
+
+ /**
+ * Start the warmup phase. This means that the load generator is started,
+ * but the results are not collected.
+ */
+ void startWarmup();
+
+ /**
+ * Move from the warmup phase to the steady-state phase. Start collecting
+ * results.
+ */
+ void startSteadyState();
+
+ /**
+ * Stop the load generator.
+ */
+ void stop();
+
+ /**
+ * Print a report from the test run.
+ *
+ * @param out stream to print the report to
+ */
+ void printReport(PrintStream out);
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/LoadGenerator.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java Thu Feb 7 05:25:24 2008
@@ -0,0 +1,199 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.PoissonLoadGenerator
+
+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.derbyTesting.perf.clients;
+
+import java.io.PrintStream;
+import java.sql.SQLException;
+import java.util.Random;
+
+/**
+ * Load generator which generates Poisson distributed requests.
+ */
+public class PoissonLoadGenerator implements LoadGenerator {
+
+ /**
+ * The average time (in milliseconds) between each request from a client.
+ */
+ private final double avgWaitTime;
+
+ /** The client threads used to generate load. */
+ private ClientThread[] threads;
+ /** Flag which tells the generator to stop. */
+ private volatile boolean stop;
+ /** Flag which tells the generator to collect results. */
+ private volatile boolean collect;
+ /** Start time for steady-state phase. */
+ private long startTime;
+ /** Stop time for steady-state phase. */
+ private long stopTime;
+
+ /**
+ * Construct a {@code PoissonLoadGenerator} instance.
+ *
+ * @param avgWaitTime the time (in millisecond) between each request from
+ * a client
+ */
+ public PoissonLoadGenerator(double avgWaitTime) {
+ this.avgWaitTime = avgWaitTime;
+ }
+
+ /**
+ * Thread class which runs a single client and collects results.
+ */
+ private class ClientThread extends Thread {
+ private final Client client;
+ private long count;
+ private long totalTime;
+ private long min = Long.MAX_VALUE;
+ private long max = 0;
+
+ ClientThread(Client c) {
+ client = c;
+ }
+
+ /**
+ * Tell the client to stop waiting.
+ */
+ synchronized void wakeup() {
+ ClientThread.this.notifyAll();
+ }
+
+ public void run() {
+ try {
+ runClient();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void runClient() throws SQLException, InterruptedException {
+ final Random r = new Random();
+ final long start = System.currentTimeMillis();
+ // use a double to prevent too short average wait time because
+ // of truncation
+ double timeOffset = 0d;
+ long now = start;
+ while (!stop) {
+ // Increase the timeOffset by a random value picked from an
+ // exponential distribution (exponentially distributed wait
+ // times give Poisson distributed requests, see
+ // http://en.wikipedia.org/wiki/Exponential_distribution)
+ timeOffset += -Math.log(r.nextDouble()) * avgWaitTime;
+ final long nextWakeup = start + (long) timeOffset;
+ while (now < nextWakeup) {
+ synchronized (ClientThread.this) {
+ if (stop) {
+ return;
+ }
+ ClientThread.this.wait(nextWakeup - now);
+ }
+ now = System.currentTimeMillis();
+ }
+
+ final long t0 = now;
+ client.doWork();
+ final long t1 = System.currentTimeMillis();
+ if (collect) {
+ final long time = t1 - t0;
+ count++;
+ totalTime += time;
+ if (time > max) max = time;
+ if (time < min) min = time;
+ }
+ now = t1;
+ }
+ }
+ }
+
+ /**
+ * Initialize the load generator.
+ *
+ * @param clients the test clients to use
+ */
+ public void init(Client[] clients) {
+ threads = new ClientThread[clients.length];
+ for (int i = 0; i < clients.length; i++) {
+ threads[i] = new ClientThread(clients[i]);
+ }
+ }
+
+ /**
+ * Start warmup phase.
+ */
+ public void startWarmup() {
+ for (int i = 0; i < threads.length; i++) {
+ threads[i].start();
+ }
+ }
+
+ /**
+ * Start steady-state phase.
+ */
+ public void startSteadyState() {
+ startTime = System.currentTimeMillis();
+ collect = true;
+ }
+
+ /**
+ * Stop the load generator.
+ */
+ public void stop() {
+ stopTime = System.currentTimeMillis();
+ collect = false;
+ stop = true;
+ for (int i = 0; i < threads.length; i++) {
+ try {
+ threads[i].wakeup();
+ threads[i].join();
+ } catch (InterruptedException ie) {
+ ie.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Print average transaction injection rate and response times.
+ */
+ public void printReport(PrintStream out) {
+ long time = stopTime - startTime;
+
+ long count = 0;
+ long totalTime = 0;
+ long min = Long.MAX_VALUE;
+ long max = 0;
+ for (int i = 0; i < threads.length; i++) {
+ count += threads[i].count;
+ totalTime += threads[i].totalTime;
+ min = Math.min(min, threads[i].min);
+ max = Math.max(max, threads[i].max);
+ }
+
+ double tps = (double) count * 1000 / time;
+ double avgResp = (double) totalTime / count;
+
+ out.println("Number of threads:\t" + threads.length);
+ out.println("Average injection rate (tx/s):\t" + tps);
+ out.println("Average response time (ms):\t" + avgResp);
+ out.println("Minimum response time (ms):\t" + min);
+ out.println("Maximum response time (ms):\t" + max);
+ }
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java Thu Feb 7 05:25:24 2008
@@ -0,0 +1,286 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.Runner
+
+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.derbyTesting.perf.clients;
+
+import java.io.PrintStream;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * Class used for running a performance test from the command line. To learn
+ * how to run the tests, invoke this command:
+ * <pre>
+ * java org.apache.derbyTesting.perf.clients.Runner
+ * </pre>
+ */
+public class Runner {
+
+ private static final String DERBY_EMBEDDED_DRIVER =
+ "org.apache.derby.jdbc.EmbeddedDriver";
+
+ private static final String DEFAULT_URL = "jdbc:derby:db;create=true";
+
+ /** The JDBC driver class to use in the test. */
+ private static String driver = DERBY_EMBEDDED_DRIVER;
+ /** The JDBC connection URL to use in the test. */
+ private static String url = DEFAULT_URL;
+ /** Username for connecting to the database. */
+ private static String user = "test";
+ /** Password for connecting to the database. */
+ private static String password = "test";
+ /**
+ * Flag which tells whether the data needed by this test should be
+ * (re)created.
+ */
+ private static boolean init = false;
+ /** The name of the type of load to use in the test. */
+ private static String load; // required argument
+ /** The name of the load generator to use in the test. */
+ private static String generator = "b2b";
+ /** The number of client threads to use in the test. */
+ private static int threads = 1;
+ /**
+ * The number of requests to issue to the database per second (for the
+ * load generators that take that as an argument).
+ */
+ private static int requestsPerSecond = 100;
+ /** The number of seconds to spend in the warmup phase. */
+ private static int warmupSec = 30;
+ /** The number of seconds to collect results. */
+ private static int steadySec = 60;
+
+ /**
+ * Main method which starts the Runner application.
+ *
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) throws Exception {
+ try {
+ parseArgs(args);
+ } catch (Exception e) {
+ System.err.println(e);
+ printUsage(System.err);
+ System.exit(1);
+ }
+
+ Class.forName(driver).newInstance();
+
+ if (init) {
+ DBFiller filler = getDBFiller();
+ Connection conn = DriverManager.getConnection(url, user, password);
+ System.out.println("initializing database...");
+ filler.fill(conn);
+ conn.close();
+ }
+
+ Client[] clients = new Client[threads];
+ for (int i = 0; i < clients.length; i++) {
+ Connection c = DriverManager.getConnection(url, user, password);
+ c.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+ clients[i] = newClient();
+ clients[i].init(c);
+ }
+
+ LoadGenerator gen = getLoadGenerator();
+ gen.init(clients);
+ System.out.println("starting warmup...");
+ gen.startWarmup();
+ Thread.sleep(1000L * warmupSec);
+ System.out.println("entering steady state...");
+ gen.startSteadyState();
+ Thread.sleep(1000L * steadySec);
+ System.out.println("stopping threads...");
+ gen.stop();
+ gen.printReport(System.out);
+
+ shutdownDatabase();
+ }
+
+ /**
+ * Parse the command line arguments and set the state variables to
+ * reflect the arguments.
+ *
+ * @param args the command line arguments
+ */
+ private static void parseArgs(String[] args) throws Exception {
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equals("-driver")) {
+ driver = args[++i];
+ } else if (args[i].equals("-url")) {
+ url = args[++i];
+ } else if (args[i].equals("-user")) {
+ user = args[++i];
+ } else if (args[i].equals("-pass")) {
+ password = args[++i];
+ } else if (args[i].equals("-init")) {
+ init = true;
+ } else if (args[i].equals("-load")) {
+ load = args[++i];
+ } else if (args[i].equals("-gen")) {
+ generator = args[++i];
+ } else if (args[i].equals("-threads")) {
+ threads = Integer.parseInt(args[++i]);
+ } else if (args[i].equals("-rate")) {
+ requestsPerSecond = Integer.parseInt(args[++i]);
+ } else if (args[i].equals("-wt")) {
+ warmupSec = Integer.parseInt(args[++i]);
+ } else if (args[i].equals("-rt")) {
+ steadySec = Integer.parseInt(args[++i]);
+ } else {
+ throw new Exception("invalid argument: " + args[i]);
+ }
+ }
+ if (load == null) {
+ throw new Exception("required parameter -load not specified");
+ }
+ }
+
+ /** String to print when there are errors in the command line arguments. */
+ private static final String USAGE =
+
+"Valid parameters:\n" +
+" -driver: JDBC driver class, default: " + DERBY_EMBEDDED_DRIVER + "\n" +
+" -url: JDBC connection url, default: " + DEFAULT_URL + "\n" +
+" -user: JDBC user name, default: test\n" +
+" -pass: JDBC user password, default: test\n" +
+" -init: initialize database (otherwise, reuse database)\n" +
+" -load: type of load, required argument, valid types:\n" +
+" * sr_select - single-record (primary key) select from table with\n" +
+" 100 000 rows\n" +
+" * sr_update - single-record (primary key) update on table with\n" +
+" 100 000 rows\n" +
+" * sr_select_big - single-record (primary key) select from table with\n" +
+" 100 000 000 rows\n" +
+" * sr_update_big - single-record (primary key) update on table with\n" +
+" 100 000 000 rows\n" +
+" * sr_select_multi - single-record select from a random table\n" +
+" (32 tables with a single row each)\n" +
+" * sr_update_multi - single-record update on a random table\n" +
+" (32 tables with a single row each)\n" +
+" * index_join - join of two tables (using indexed columns)\n" +
+" -gen: load generator, default: b2b, valid types:\n" +
+" * b2b - clients perform operations back-to-back\n" +
+" * poisson - load is Poisson distributed\n" +
+" -threads: number of threads performing operations, default: 1\n" +
+" -rate: average number of transactions per second to inject when\n" +
+" load generator is \"poisson\", default: 100\n" +
+" -wt: warmup time in seconds, default: 30\n" +
+" -rt: time in seconds to collect results, default: 60";
+
+ /**
+ * Print the usage string.
+ *
+ * @param out the stream to print the usage string to
+ */
+ private static void printUsage(PrintStream out) {
+ out.println(USAGE);
+ }
+
+ /**
+ * Find the {@code DBFiller} instance for the load specified on the
+ * command line.
+ *
+ * @return a {@code DBFiller} instance
+ */
+ private static DBFiller getDBFiller() {
+ if (load.equals("sr_select") || load.equals("sr_update")) {
+ return new SingleRecordFiller(100000, 1);
+ } else if (load.equals("sr_select_big") ||
+ load.equals("sr_update_big")) {
+ return new SingleRecordFiller(100000000, 1);
+ } else if (load.equals("sr_select_multi") ||
+ load.equals("sr_update_multi")) {
+ return new SingleRecordFiller(1, 32);
+ } else if (load.equals("index_join")) {
+ return new WisconsinFiller();
+ }
+ System.err.println("unknown load: " + load);
+ printUsage(System.err);
+ System.exit(1);
+ return null;
+ }
+
+ /**
+ * Create a new client for the load specified on the command line.
+ *
+ * @return a {@code Client} instance
+ */
+ private static Client newClient() {
+ if (load.equals("sr_select")) {
+ return new SingleRecordSelectClient(100000, 1);
+ } else if (load.equals("sr_update")) {
+ return new SingleRecordUpdateClient(100000, 1);
+ } else if (load.equals("sr_select_big")) {
+ return new SingleRecordSelectClient(100000000, 1);
+ } else if (load.equals("sr_update_big")) {
+ return new SingleRecordUpdateClient(100000000, 1);
+ } else if (load.equals("sr_select_multi")) {
+ return new SingleRecordSelectClient(1, 32);
+ } else if (load.equals("sr_update_multi")) {
+ return new SingleRecordUpdateClient(1, 32);
+ } else if (load.equals("index_join")) {
+ return new IndexJoinClient();
+ }
+ System.err.println("unknown load: " + load);
+ printUsage(System.err);
+ System.exit(1);
+ return null;
+ }
+
+ /**
+ * Create a load generator for the load specified on the command line.
+ *
+ * @return a {@code LoadGenerator} instance
+ */
+ private static LoadGenerator getLoadGenerator() {
+ if (generator.equals("b2b")) {
+ return new BackToBackLoadGenerator();
+ } else if (generator.equals("poisson")) {
+ double avgWaitTime = 1000d * threads / requestsPerSecond;
+ return new PoissonLoadGenerator(avgWaitTime);
+ }
+ System.err.println("unknown load generator: " + generator);
+ printUsage(System.err);
+ System.exit(1);
+ return null;
+ }
+
+ /**
+ * Shut down the database if it is a Derby embedded database.
+ */
+ private static void shutdownDatabase() throws SQLException {
+ if (driver.equals(DERBY_EMBEDDED_DRIVER)) {
+ try {
+ DriverManager.getConnection(url + ";shutdown=true");
+ System.err.println("WARNING: Shutdown of database didn't " +
+ "throw expected exception");
+ } catch (SQLException e) {
+ if (!"08006".equals(e.getSQLState())) {
+ System.err.println("WARNING: Shutdown of database threw " +
+ "unexpected exception");
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordFiller.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordFiller.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordFiller.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordFiller.java Thu Feb 7 05:25:24 2008
@@ -0,0 +1,121 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.SingleRecordFiller
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Random;
+
+/**
+ * Class which generates and populates tables that can be used by
+ * {@code SingleRecordSelectClient} and {@code SingleRecordUpdateClient}.
+ * This tables contain rows with an int column (id) and a varchar(100) column
+ * (text). The id column is declared as primary key.
+ */
+public class SingleRecordFiller implements DBFiller {
+
+ private final int numberOfTables;
+ private final int tableSize;
+
+ private static final int TEXT_SIZE = 100;
+
+ /**
+ * Generate a filler that creates the specified number of tables, each of
+ * which contains the specified number of records.
+ *
+ * @param records the number of records in each table
+ * @param tables the number of tables to create
+ */
+ public SingleRecordFiller(int records, int tables) {
+ tableSize = records;
+ numberOfTables = tables;
+ }
+
+ public void fill(Connection c) throws SQLException {
+ c.setAutoCommit(false);
+ Statement s = c.createStatement();
+ for (int table = 0; table < numberOfTables; table++) {
+ String tableName = getTableName(tableSize, table);
+ WisconsinFiller.dropTable(c, tableName);
+ s.executeUpdate(
+ "CREATE TABLE " + tableName + "(ID INT PRIMARY KEY, " +
+ "TEXT VARCHAR(" + TEXT_SIZE + "))");
+
+ PreparedStatement ps =
+ c.prepareStatement("INSERT INTO " + tableName +
+ "(ID, TEXT) VALUES (?, ?)");
+
+ for (int i = 0; i < tableSize; i++) {
+ ps.setInt(1, i);
+ ps.setString(2, randomString(i));
+ ps.executeUpdate();
+ if ((i % 1000) == 0) {
+ c.commit();
+ }
+ }
+
+ ps.close();
+ c.commit();
+ }
+
+ s.close();
+ }
+
+ private static final String[] RANDOM_STRINGS = new String[16];
+ static {
+ final String alphabet = "abcdefghijklmnopqrstuvwxyz" +
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+ "01234567890_-+*/(){}[]&%$#!";
+ final Random r = new Random();
+ for (int i = 0; i < RANDOM_STRINGS.length; i++) {
+ StringBuffer buf = new StringBuffer(TEXT_SIZE);
+ for (int x = 0; x < TEXT_SIZE; x++) {
+ buf.append(alphabet.charAt(r.nextInt(alphabet.length())));
+ }
+ RANDOM_STRINGS[i] = buf.toString();
+ }
+ }
+
+ /**
+ * Pick a random string.
+ *
+ * @param seed a seed used to decide which random string to pick
+ * @return a (somewhat) random string
+ */
+ static String randomString(int seed) {
+ return RANDOM_STRINGS[(seed & 0x7fffffff) % RANDOM_STRINGS.length];
+ }
+
+ /**
+ * Get the name of a table generated by this class.
+ *
+ * @param records the number of records in the table
+ * @param table the number of the table, between 0 (inclusive) and the
+ * total number of tables (exclusive)
+ * @return the name of the table specified by the arguments
+ */
+ static String getTableName(int records, int table) {
+ return "SINGLE_RECORD_" + records + "_" + table;
+ }
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordFiller.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java Thu Feb 7 05:25:24 2008
@@ -0,0 +1,76 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.SingleRecordSelectClient
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Random;
+
+/**
+ * Client which performs single-record lookups on tables generated by
+ * {@code SingleRecordFiller}. Each time the client's {@code doWork()} method
+ * is called, it will pick one of the tables randomly, and select one random
+ * record in that table.
+ */
+public class SingleRecordSelectClient implements Client {
+
+ private Connection conn;
+
+ private final PreparedStatement[] pss;
+ private final Random r;
+ private final int tableSize;
+
+ /**
+ * Construct a new single-record select client.
+ *
+ * @param records the number of records in each table in the test
+ * @param tables the number of tables in the test
+ */
+ public SingleRecordSelectClient(int records, int tables) {
+ tableSize = records;
+ r = new Random();
+ pss = new PreparedStatement[tables];
+ }
+
+ public void init(Connection c) throws SQLException {
+ for (int i = 0; i < pss.length; i++) {
+ String tableName = SingleRecordFiller.getTableName(tableSize, i);
+ String sql = "SELECT * FROM " + tableName + " WHERE ID = ?";
+ pss[i] = c.prepareStatement(sql);
+ }
+ c.setAutoCommit(false);
+ conn = c;
+ }
+
+ public void doWork() throws SQLException {
+ PreparedStatement ps = pss[r.nextInt(pss.length)];
+ ps.setInt(1, r.nextInt(tableSize));
+ ResultSet rs = ps.executeQuery();
+ rs.next();
+ rs.getInt(1);
+ rs.getString(2);
+ rs.close();
+ conn.commit();
+ }
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java Thu Feb 7 05:25:24 2008
@@ -0,0 +1,73 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.SingleRecordUpdateClient
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Random;
+
+/**
+ * Client which updates a single record at a time on tables generated by
+ * {@code SingleRecordFiller}. Each time the client's {@code doWork()} method
+ * is called, it will pick one of the tables randomly, and update the text
+ * column of one random record in that table.
+ */
+public class SingleRecordUpdateClient implements Client {
+
+ private Connection conn;
+
+ private final PreparedStatement[] pss;
+ private final Random r;
+ private final int tableSize;
+
+ /**
+ * Construct a new single-record update client.
+ *
+ * @param records the number of records in each table in the test
+ * @param tables the number of tables in the test
+ */
+ public SingleRecordUpdateClient(int records, int tables) {
+ tableSize = records;
+ r = new Random();
+ pss = new PreparedStatement[tables];
+ }
+
+ public void init(Connection c) throws SQLException {
+ for (int i = 0; i < pss.length; i++) {
+ String tableName = SingleRecordFiller.getTableName(tableSize, i);
+ String sql = "UPDATE " + tableName + " SET TEXT = ? WHERE ID = ?";
+ pss[i] = c.prepareStatement(sql);
+ }
+ c.setAutoCommit(false);
+ conn = c;
+ }
+
+ public void doWork() throws SQLException {
+ PreparedStatement ps = pss[r.nextInt(pss.length)];
+ ps.setString(1, SingleRecordFiller.randomString(r.nextInt()));
+ ps.setInt(2, r.nextInt(tableSize));
+ ps.executeUpdate();
+ conn.commit();
+ }
+
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/WisconsinFiller.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/WisconsinFiller.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/WisconsinFiller.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/WisconsinFiller.java Thu Feb 7 05:25:24 2008
@@ -0,0 +1,75 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.WisconsinFiller
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import org.apache.derbyTesting.functionTests.tests.lang.wisconsin;
+
+/**
+ * Class which creates and populates the tables used by
+ * {@code IndexJoinClient}. These are the same tables as the ones used by the
+ * functional Wisconsin test found in the lang suite.
+ */
+public class WisconsinFiller implements DBFiller {
+
+ public void fill(Connection c) throws SQLException {
+ c.setAutoCommit(false);
+
+ dropTable(c, "TENKTUP1");
+ dropTable(c, "TENKTUP2");
+ dropTable(c, "ONEKTUP");
+ dropTable(c, "BPRIME");
+
+ wisconsin.createTables(c, false);
+
+ c.commit();
+ }
+
+ /**
+ * Helper method which drops a table if it exists. Nothing happens if
+ * the table doesn't exist.
+ *
+ * @param c the connection to use
+ * @param table the table to drop
+ * @throws SQLException if an unexpected database error occurs
+ */
+ static void dropTable(Connection c, String table) throws SQLException {
+ // Create a savepoint that we can roll back to if drop table fails.
+ // This is not needed by Derby, but some databases (e.g., PostgreSQL)
+ // don't allow more operations in a transaction if a statement fails,
+ // and we want to be able to run these tests against other databases
+ // than Derby.
+ Savepoint sp = c.setSavepoint();
+ Statement stmt = c.createStatement();
+ try {
+ stmt.executeUpdate("DROP TABLE " + table);
+ } catch (SQLException e) {
+ // OK to fail if table doesn't exist, roll back to savepoint
+ c.rollback(sp);
+ }
+ stmt.close();
+ c.releaseSavepoint(sp);
+ }
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/WisconsinFiller.java
------------------------------------------------------------------------------
svn:eol-style = native