From: <jz...@us...> - 2009-10-21 10:38:35
|
Revision: 569 http://dacapobench.svn.sourceforge.net/dacapobench/?rev=569&view=rev Author: jzigman Date: 2009-10-21 10:38:25 +0000 (Wed, 21 Oct 2009) Log Message: ----------- Replaced the Derby benchmark with the H2 benchmark. The H2 database is tested with a TPC-C like workload provided by the derbyTesting.jar from Derby 10.5.3.0. Added the h2 benchmark, removed derby benchmark, added the derby library. Modified the libs and build to reflect these changes. Modified Paths: -------------- benchmarks/trunk/benchmarks/build.xml benchmarks/trunk/benchmarks/libs/libs.xml Added Paths: ----------- benchmarks/trunk/benchmarks/bms/h2/ benchmarks/trunk/benchmarks/bms/h2/build.xml benchmarks/trunk/benchmarks/bms/h2/downloads/ benchmarks/trunk/benchmarks/bms/h2/h2.cnf benchmarks/trunk/benchmarks/bms/h2/src/ benchmarks/trunk/benchmarks/bms/h2/src/org/ benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/ benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/derby/ benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/ benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/Operation.java benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/TPCC.java benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/TPCCDataSource.java benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/TPCCSubmitter.java benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/harness/ benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/harness/H2.java benchmarks/trunk/benchmarks/libs/derby/ benchmarks/trunk/benchmarks/libs/derby/build.xml benchmarks/trunk/benchmarks/libs/derby/downloads/ benchmarks/trunk/benchmarks/libs/derby/downloads/db-derby-10.5.3.0-src.tar.gz.MD5 Removed Paths: ------------- benchmarks/trunk/benchmarks/bms/derby/ Added: benchmarks/trunk/benchmarks/bms/h2/build.xml =================================================================== --- benchmarks/trunk/benchmarks/bms/h2/build.xml (rev 0) +++ benchmarks/trunk/benchmarks/bms/h2/build.xml 2009-10-21 10:38:25 UTC (rev 569) @@ -0,0 +1,40 @@ +<project name="h2" default="all" basedir="../.."> + <description>DaCapo h2 benchmark</description> + <property file="dacapo.properties"/> + + <property name="bm-name" value="h2"/> + + <import file="../common.xml"/> + + <target name="bm-harness" depends="junit,h2,derby"> + <javac srcdir="${bm-src-dir}" destdir="${bm-output-dir}" + sourcepath="${bm-src-dir}" + source="1.5" + debug="true" debuglevel="lines,vars,source"> + <classpath> + <!-- note that the jars build are either in the jars/sane or jars/insane + directory depending upon the build environment, however, they are + never in both directories --> + <pathelement location="${derbytesting-jar}"/> + + <pathelement location="${h2-jar}"/> + + <pathelement location="${junit-jar}"/> + + <pathelement path="${bm-output-dir}"/> + + <pathelement path="${harness-classpath}"/> + </classpath> + </javac> + <jar destfile="${bm-jars}/tpcc.jar"> + <fileset dir="${bm-output-dir}"> + <include name="org/dacapo/h2/**"/> + </fileset> + </jar> + <delete dir="${bm-output-dir}/org/dacapo/h2"/> + </target> + + <target name="bm-build" depends="junit,h2,derby"/> + +</project> + Added: benchmarks/trunk/benchmarks/bms/h2/h2.cnf =================================================================== --- benchmarks/trunk/benchmarks/bms/h2/h2.cnf (rev 0) +++ benchmarks/trunk/benchmarks/bms/h2/h2.cnf 2009-10-21 10:38:25 UTC (rev 569) @@ -0,0 +1,43 @@ +benchmark h2 + class org.dacapo.harness.H2 + thread-model per_cpu + libs "derbyTesting.jar","junit-3.8.1.jar","h2-1.2.121.jar","tpcc.jar"; + +size small args "-numberOfTerminals","${THREADS}", + "-totalTransactions", "3200", + "-scale","1", + "-numberOfWarehouses", "1", + "-retryLimit", "10", + "-createSuffix", ";MVCC=true" + threads 1 + output stdout digest 0xc288238cd21fe6190545de5c9cd896b0e5b66a9d; + +size default args "-numberOfTerminals","${THREADS}", + "-totalTransactions","12800", + "-scale","1", + "-numberOfWarehouses", "1", + "-retryLimit", "10", + "-createSuffix", ";MVCC=true" + threads 1 + output stdout digest 0x782c90958012af6327f433b70a85a1b1841a0606; + +size large args "-numberOfTerminals","${THREADS}", + "-totalTransactions","51200", + "-scale","1", + "-numberOfWarehouses", "1", + "-retryLimit", "10", + "-createSuffix", ";MVCC=true" + threads 1 + output stdout digest 0xe50827b7a55671b6455676390db41f2edc77c994; + + +description + short "An SQL relational database engine written in Java", + long "H2 executes a TPC-C like benchmark written by Apache as part of the Apache Derby database. The application models: customers, districts, warehouses, purchases and deliveries.", + copyright "Copyright (c) 2001-2002, The Apache Software Foundation and H2 Group, H2", + author "TPC-C like workload authored by The Apache Software Foundation, and Database authored by H2", + license "Apache License, Version 2.0 covering TPC-C like workload, and Eclipse Public License Version 1.0 covering H2", + url "http://db.apache.org/derby/ and http://www.h2database.com", + version "10.5.3.0 and 1.2.121", + repeats "12800 Transactions evenly divided amoung the hardware threads.", + threads "One client thread per hardware thread."; Added: benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/Operation.java =================================================================== --- benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/Operation.java (rev 0) +++ benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/Operation.java 2009-10-21 10:38:25 UTC (rev 569) @@ -0,0 +1,325 @@ +/* + * + * Derby - Class org.apache.derbyTesting.system.oe.direct.Standard + * + * 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. + * + * Contributors: + * Apache Software Foundation (ASF) - initial API and implementation + * Australian National University - adaptation to DaCapo test harness + */ +package org.dacapo.h2; + +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; + +import org.apache.derbyTesting.system.oe.client.Display; +import org.apache.derbyTesting.system.oe.direct.Standard; +import org.apache.derbyTesting.system.oe.routines.Data; +import org.apache.derbyTesting.system.oe.model.Customer; +import org.apache.derbyTesting.system.oe.model.District; +import org.apache.derbyTesting.system.oe.model.Warehouse; + +/** + * Construct a wrapper sub-classs of the + * org.apache.derbyTesting.system.oe.direct.Standard + * operations class, which can be found in: + * db-derby-10.5.3.0-src/java/testing/org/apache/derbyTesting/system/oe/direct/Standard.java + * in the + * http://apache.wildit.net.au/db/derby/db-derby-10.5.3.0/db-derby-10.5.3.0-src.tar.gz + * + * This class is created as the parent class uses a Java call-back for + * updating C_DATA for a client which Derby understands but H2 does not. + * Thus, we override both <code>payment</code> methods copying the code + * from the parent class (Standard) to this class so that we can make a + * call to the modified version of <code>paymentById</code>. + * + * The method <code>paymentById</code> is taken from the clas Standard + * and is modified to remove the call-back. + */ +public final class Operation extends Standard +{ + + /** + * @param conn + * A connection to the derby database. + * @param retryLimit + * The maximum number of retries before catastrophic failure. + * @throws SQLException + */ + public Operation(Connection conn) throws SQLException + { + super(conn); + } + + // The following two payment methods are taken verbatim from + // org.apache.derbyTesting.system.oe.direct.Standard + // so that we can in effect override the private method paymentById + /** + * Payment by customer last name. + * Section 2.5.2 + * The CUSTOMER row will be fetched and then updated. + * This is due to the need to select the specific customer + * first based upon last name (which will actually fetch and + * hence lock a number of customers). + */ + public void payment(Display display, Object displayData, short w, short d, + short cw, short cd, String customerLast, String amount) + throws Exception { + + PreparedStatement pyCustomerByName = prepareStatement( + "SELECT C_ID " + + "FROM CUSTOMER WHERE C_W_ID = ? AND C_D_ID = ? AND C_LAST = ? " + + "ORDER BY C_FIRST"); + + // Since so much data is needed for the payment transaction + // from the customer we don't fill it in as we select the + // correct customer. Instead we just fetch the identifier + // and then execute a payment by identifier. + try { + pyCustomerByName.setShort(1, cw); + pyCustomerByName.setShort(2, cd); + pyCustomerByName.setString(3, customerLast); + ResultSet rs = pyCustomerByName.executeQuery(); + + nameList.clear(); + while (rs.next()) + { + nameList.add(rs.getObject("C_ID")); + } + reset(pyCustomerByName); + if (nameList.isEmpty()) + throw new SQLException("Payment by name - no matching customer " + + customerLast); + + // Customer to use is midpoint (with round up) (see 2.5.2.2) + int mid = nameList.size()/2; + if (mid != 0) { + if (nameList.size()%2 == 1) + mid++; + } + + int c = ((Integer) nameList.get(mid)).intValue(); + + paymentById(display, displayData, w, d, cw, cd, c, amount); + } catch (SQLException e) { + conn.rollback(); + throw e; + } + + if (display != null) + ; + } + + /** + * Payment by customer identifier. + * Section 2.5.2. + * The CUSTOMER row is update and then fetched. + * + */ + public void payment(Display display, Object displayData, short w, short d, + short cw, short cd, int c, final String amount) throws Exception { + + try { + paymentById(display, displayData, w, d, cw, cd, c, amount); + } catch (SQLException e) { + conn.rollback(); + throw e; + } + + if (display != null) + ; + } + + // Modified operations from Standard, replaced due to callback in to Java that + // is not supported on most SQL. + /* + * Objects for re-use within the transactions + */ + private final Warehouse warehouse = new Warehouse(); + private final District district = new District(); + private final List nameList = new ArrayList(); + + private void paymentById(Display display, Object displayData, short w, short d, + short cw, short cd, int c, final String s_amount) throws Exception { + + PreparedStatement pyCustomerPayment = prepareStatement( + "UPDATE CUSTOMER SET C_BALANCE = C_BALANCE - ?, " + + "C_YTD_PAYMENT = C_YTD_PAYMENT + ?, " + + "C_PAYMENT_CNT = C_PAYMENT_CNT + 1 " + + "WHERE C_W_ID = ? AND C_D_ID = ? AND C_ID = ?"); + + PreparedStatement pyCustomerInfoId = prepareStatement( + "SELECT C_FIRST, C_MIDDLE, C_LAST, C_BALANCE, " + + "C_STREET_1, C_STREET_2, C_CITY, C_STATE, C_ZIP, " + + "C_PHONE, C_SINCE, C_CREDIT, C_CREDIT_LIM, C_DISCOUNT, C_DATA " + + "FROM CUSTOMER WHERE C_W_ID = ? AND C_D_ID = ? AND C_ID = ?"); + + // This is removed as the call out to java from the SQL engine did not work + // from H2, this value can be calculated externally and set so this callback + // is somewhat redundant. + PreparedStatement pyCustomerUpdateBadCredit = prepareStatement( + // "UPDATE CUSTOMER SET C_DATA = " + + // " BAD_CREDIT_DATA(C_DATA, ?, ?, C_W_ID, C_W_ID, C_ID, ?) " + + "UPDATE CUSTOMER SET C_DATA = ? " + + "WHERE C_W_ID = ? AND C_D_ID = ? AND C_ID = ?"); + + PreparedStatement pyCustomerGetData = prepareStatement( + "SELECT SUBSTR(C_DATA, 1, 200) AS C_DATA_200 " + + "FROM CUSTOMER WHERE C_W_ID = ? AND C_D_ID = ? AND C_ID = ?"); + + PreparedStatement pyDistrictUpdate = prepareStatement( + "UPDATE DISTRICT SET D_YTD = D_YTD + ? WHERE D_W_ID = ? AND D_ID = ?"); + PreparedStatement pyDistrictInfo = prepareStatement( + "SELECT D_NAME, D_STREET_1, D_STREET_2, D_CITY, D_STATE, D_ZIP FROM DISTRICT WHERE D_W_ID = ? AND D_ID = ? "); + PreparedStatement pyWarehouseUpdate = prepareStatement( + "UPDATE WAREHOUSE SET W_YTD = W_YTD + ? WHERE W_ID = ?"); + PreparedStatement pyWarehouseInfo = prepareStatement( + "SELECT W_NAME, W_STREET_1, W_STREET_2, W_CITY, W_STATE, W_ZIP " + + "FROM WAREHOUSE WHERE W_ID = ?"); + + PreparedStatement pyHistory = prepareStatement( + "INSERT INTO HISTORY(H_C_ID, H_C_D_ID, H_C_W_ID, H_D_ID, H_W_ID, " + + "H_AMOUNT, H_DATA, H_DATE) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); + + Customer customer = new Customer(); + customer.setWarehouse(cw); + customer.setDistrict(cd); + customer.setId(c); + + double d_amount = Double.parseDouble(s_amount); + + // Update the customer assuming that they have good credit + pyCustomerPayment.setDouble(1, d_amount); + pyCustomerPayment.setDouble(2, d_amount); + pyCustomerPayment.setShort(3, cw); + pyCustomerPayment.setShort(4, cd); + pyCustomerPayment.setInt(5, c); + pyCustomerPayment.executeUpdate(); + + // Get the customer information + pyCustomerInfoId.setShort(1, cw); + pyCustomerInfoId.setShort(2, cd); + pyCustomerInfoId.setInt(3, c); + ResultSet rs = pyCustomerInfoId.executeQuery(); + rs.next(); + + customer.setFirst(rs.getString("C_FIRST")); + customer.setMiddle(rs.getString("C_MIDDLE")); + customer.setLast(rs.getString("C_LAST")); + customer.setBalance(rs.getString("C_BALANCE")); + + customer.setAddress(getAddress(rs, "C_STREET_1")); + + customer.setPhone(rs.getString("C_PHONE")); + customer.setSince(rs.getTimestamp("C_SINCE")); + customer.setCredit(rs.getString("C_CREDIT")); + customer.setCredit_lim(rs.getString("C_CREDIT_LIM")); + customer.setDiscount(rs.getString("C_DISCOUNT")); + customer.setData(rs.getString("C_DATA")); + reset(pyCustomerInfoId); + + // additional work for bad credit customers. + if ("BC".equals(customer.getCredit())) + { + // The following line is added (and indexes changed) as the field can be + // calculated externally and the callback mechanism is not usable under H2. + pyCustomerUpdateBadCredit.setString(1, Data.dataForBadCredit(customer.getData(), w, d, cw, cd, c, new BigDecimal(s_amount))); + pyCustomerUpdateBadCredit.setShort(2, cw); + pyCustomerUpdateBadCredit.setShort(3, cd); + pyCustomerUpdateBadCredit.setInt(4, c); + pyCustomerUpdateBadCredit.executeUpdate(); + reset(pyCustomerUpdateBadCredit); + + // Need to display the first 200 characters + // of C_DATA information if the customer has + // bad credit. + pyCustomerGetData.setShort(1, cw); + pyCustomerGetData.setShort(2, cd); + pyCustomerGetData.setInt(3, c); + rs = pyCustomerGetData.executeQuery(); + rs.next(); + customer.setData(rs.getString("C_DATA_200")); + reset(pyCustomerGetData); + } + + district.clear(); + district.setWarehouse(w); + district.setId(d); + + // Update DISTRICT + pyDistrictUpdate.setDouble(1, d_amount); + pyDistrictUpdate.setShort(2, w); + pyDistrictUpdate.setShort(3, d); + pyDistrictUpdate.executeUpdate(); + reset(pyDistrictUpdate); + + // Get the required information from DISTRICT + pyDistrictInfo.setShort(1, w); + pyDistrictInfo.setShort(2, d); + rs = pyDistrictInfo.executeQuery(); + rs.next(); + district.setName(rs.getString("D_NAME")); + district.setAddress(getAddress(rs, "D_STREET_1")); + reset(pyDistrictInfo); + + warehouse.clear(); + warehouse.setId(w); + + // Update WAREHOUSE + pyWarehouseUpdate.setDouble(1, d_amount); + pyWarehouseUpdate.setShort(2, w); + pyWarehouseUpdate.executeUpdate(); + reset(pyWarehouseUpdate); + + // Get the required information from WAREHOUSE + pyWarehouseInfo.setShort(1, w); + rs = pyWarehouseInfo.executeQuery(); + rs.next(); + warehouse.setName(rs.getString("W_NAME")); + warehouse.setAddress(getAddress(rs, "W_STREET_1")); + reset(pyWarehouseInfo); + + Timestamp currentTimeStamp = new Timestamp(System.currentTimeMillis()); + + + // Insert HISTORY row + pyHistory.setInt(1, c); + pyHistory.setShort(2, cd); + pyHistory.setShort(3, cw); + pyHistory.setShort(4, d); + pyHistory.setShort(5, w); + pyHistory.setDouble(6, d_amount); + StringBuffer hData = new StringBuffer(24); + hData.append(warehouse.getName()); + hData.append(" "); + hData.append(district.getName()); + pyHistory.setString(7, hData.toString()); + pyHistory.setTimestamp(8, currentTimeStamp); + pyHistory.executeUpdate(); + reset(pyHistory); + + conn.commit(); + + } +} Added: benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/TPCC.java =================================================================== --- benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/TPCC.java (rev 0) +++ benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/TPCC.java 2009-10-21 10:38:25 UTC (rev 569) @@ -0,0 +1,480 @@ +package org.dacapo.h2; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.net.URL; +import java.security.AccessController; +import java.sql.Connection; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Properties; + +import javax.sql.DataSource; + +import org.apache.derbyTesting.system.oe.client.Display; +import org.apache.derbyTesting.system.oe.client.Load; +import org.apache.derbyTesting.system.oe.client.MultiThreadSubmitter; +import org.apache.derbyTesting.system.oe.client.Operations; +import org.apache.derbyTesting.system.oe.client.Submitter; +import org.apache.derbyTesting.system.oe.load.ThreadInsert; +import org.apache.derbyTesting.system.oe.util.OERandom; + +import org.dacapo.parser.Config; +import org.h2.tools.RunScript; + +public class TPCC +{ + public final static int RETRY_LIMIT = 5; + + // h2 driver settings + private final static String DRIVER_NAME = "org.h2.Driver"; + private final static String URL_BASE = "jdbc:h2:"; + private final static String DATABASE_NAME = "mem:testdb"; + private final static String CREATE_SUFFIX = ""; + + private final static String USERNAME = "user"; + private final static String PASSWORD = "password"; + private final static String USER = "derby"; + private final static String PASS = "derby"; + + // default configuration for external testing of derby + //database scale (see TPC-C documentation) number of terminals (clients) that run transactions + private final static int DEF_NUM_OF_TERMINALS = 2; + // database scale (see TPC-C documentation) + private final static short DEF_SCALE = 1; + // number of transactions each terminal (client) runs + private final static int DEF_TRANSACTIONS_PER_TERMINAL = 100; + // number of warehoueses (see TPC-C documentation) + private final static short DEF_NUM_OF_WAREHOUSES = 1; + + // Basic configurable items + // number of threads to perform loading of the database + private int loaderThreads = 1; + + // this loaderThreads seems determininstic and should be + // to the number of CPU cores + private short scale = DEF_SCALE; + private int numberOfTerminals = DEF_NUM_OF_TERMINALS; + private int transactionsPerTerminal = DEF_TRANSACTIONS_PER_TERMINAL; + private short numberOfWarehouses = DEF_NUM_OF_WAREHOUSES; + + // OLTP runners + private Connection[] connections; + private Submitter[] submitters; + private Display[] displays; + private OERandom[] rands; + + private Config config; + private String size; + private Driver driver; + private Properties properties; + private Connection conn; + + // Location of the database, this specifies the directory (folder) on a file + // system where the database is stored. This application must have be able to + // create this directory (folder) + private String database; + + private String createSuffix = CREATE_SUFFIX; + + // A random seed for initializing the database and the OLTP terminals. + private final static long SEED = 897523978813691l; + private final static int SEED_STEP = 100000; + + public static TPCC make(Config config, File scratch) throws Exception + { + return new TPCC(config, scratch); + } + + public TPCC(Config config, File scratch) throws Exception + { + this.config = config; + + // seem to need to set this early and in the system properties + Class.forName(DRIVER_NAME); + driver = DriverManager.getDriver(URL_BASE + DATABASE_NAME); + + properties = (Properties) System.getProperties().clone(); + + // make the database relative to the scratch location + if (inMemoryDB()) + database = DATABASE_NAME; + else + database = new File(scratch, DATABASE_NAME).getAbsolutePath(); + + properties.setProperty(USERNAME, USER); + properties.setProperty(PASSWORD, PASS); + } + + public void prepare(String size) throws Exception + { + this.size = size; + + configure(); + + // make a seeded random number generator for each submitter + rands = new OERandom[numberOfTerminals]; + + // for the moment we are not interested displaying the results of each + // transaction so we leave each entry in the displays array as a null + displays = new Display[numberOfTerminals]; + + // create a set of Submitter each with a Standard operations implementation + connections = new Connection[numberOfTerminals]; + submitters = new Submitter[numberOfTerminals]; + } + + public void preIteration(String size) throws Exception + { + // we can't change size after the initial prepare(size) + assert this.size.equalsIgnoreCase(size); + + // create schema + createSchema(); + + // load data + loadData(); + + // create constraints (post load, may want to move this pre load) + createConstraints(); + + // hang on to the connection until after the iteration is complete + + // make sure we have the same seeds each run + for (int i = 0; i < rands.length; i++) + { + rands[i] = new OERandom(SEED_STEP * i, SEED + SEED_STEP * i); + } + + // create a Submitter for each thread, and then pass to + // org.apache.derbyTesting.system.oe.client.MultiThreadSubmitter.multiRun + for (int i = 0; i < submitters.length; i++) + { + connections[i] = makeConnection(false); + + Operations ops = new Operation(connections[i]); + + submitters[i] = new TPCCSubmitter(null, ops, rands[i], numberOfWarehouses); + } + + // clean up any hang-over from previous iterations + System.gc(); + } + + public void iteration(String size) throws Exception + { + // we can't change size after the initial prepare(size) + assert this.size.equalsIgnoreCase(size); + + MultiThreadSubmitter.multiRun(submitters, displays, transactionsPerTerminal); + + System.out.println(); + + report(System.err); + } + + public void postIteration(String size) throws Exception + { + // we can't change size after the initial prepare(size) + assert this.size.equalsIgnoreCase(size); + + for (int i = 0; i < submitters.length; i++) + { + submitters[i] = null; + connections[i].close(); + connections[i] = null; + } + + closeConnection(); + } + + public void cleanup() throws Exception + { + deleteDatabase(); + } + + // ---------------------------------------------------------------------------------- + private void report(PrintStream os) + { + os.println("BEGIN: transaction count report"); + for (int i = 0; i < submitters.length; i++) + { + submitters[i].printReport(os); + } + os.println("END: transaction count report"); + } + + private void createSchema() throws Exception + { + // create schema + runScript("schema.sql"); + runScript("delivery.sql"); + } + + private void createConstraints() throws Exception + { + // create key constraints + runScript("primarykey.sql"); + runScript("foreignkey.sql"); + runScript("index.sql"); + } + + private void loadData() throws Exception + { + + // Use simple insert statements to insert data. + // currently only this form of load is present, once we have + // different implementations, the loading mechanism will need + // to be configurable taking an option from the command line + // arguments. + DataSource ds = new TPCCDataSource(driver, database, properties); + + Load loader = new ThreadInsert(ds); + loader.setSeed(SEED); + loader.setupLoad(getConnection(), scale); + if (loaderThreads > 0) + loader.setThreadCount(loaderThreads); + + loader.populateAllTables(); + + // Way to populate data is extensible. Any other implementation + // of org.apache.derbyTesting.system.oe.client.Load can be used + // to load data. configurable using the oe.load.insert property + // that is defined in oe.properties + // One extension would be to have an implementation that + // uses bulkinsert vti to load data. + + return; + } + + // helper function for getting and setting a connection for initial + // setup of the database + private Connection getConnection() throws SQLException + { + if (conn != null) + { + if (!conn.isClosed()) + return conn; + conn = null; + } + return conn = makeConnection(true); + } + + private void closeConnection() throws SQLException + { + if (conn != null) + { + if (!conn.isClosed()) + { + try + { + conn.commit(); + } finally + { + conn.close(); + } + } + } + conn = null; + } + + // helper functions to run sql schema and database creation scripts + private void runScript(String scriptBase) throws Exception + { + + String script = "org/apache/derbyTesting/system/oe/schema/" + scriptBase; + int errorCount = runScript(script, "US-ASCII"); + assert errorCount == 0; + } + + public int runScript(String resource, String encoding) throws Exception + { + + URL sql = getTestResource(resource); + + assert sql != null; + + InputStream sqlIn = openTestResource(sql); + Connection conn = getConnection(); + int numErrors = runScript(sqlIn, encoding); + sqlIn.close(); + + if (!conn.isClosed() && !conn.getAutoCommit()) + conn.commit(); + + return numErrors; + } + + public int runScript(InputStream script, String encoding) throws Exception + { + ResultSet results = RunScript.execute(getConnection(), new InputStreamReader(script)); + + if (results!=null) results.close(); + + return 0; + } + + // helper function for getting database setup and creation scripts + private static URL getTestResource(final String name) + { + + return (URL) AccessController.doPrivileged(new java.security.PrivilegedAction() { + + public Object run() + { + return TPCC.class.getClassLoader().getResource(name); + + } + + }); + } + + private static InputStream openTestResource(final URL url) throws Exception + { + return (InputStream) AccessController + .doPrivileged(new java.security.PrivilegedExceptionAction() { + + public Object run() throws IOException + { + return url.openStream(); + + } + + }); + } + + // construct a database connection + private Connection makeConnection(boolean create) throws SQLException + { + Properties prop = properties; + if (create) + { + prop = (Properties) properties.clone(); + // add create properties to the set of properties + prop.setProperty("create", "true"); + } + + return driver.connect(URL_BASE + getDatabaseName() + (create?createSuffix:""), prop); + } + + // database name helper functions + private String getDatabaseName() + { + return database; + } + + // helper function for recursively deleting the database directory + private boolean deleteDatabase() + { + if (inMemoryDB()) + return true; + else + return deleteDirectory(new File(database)); + } + + private boolean inMemoryDB() { + return DATABASE_NAME.startsWith("mem:") || DATABASE_NAME.startsWith("memory:"); // || true; + } + + private static boolean deleteDirectory(File path) + { + if (path.exists()) + { + File[] files = path.listFiles(); + for (int i = 0; i < files.length; i++) + { + if (files[i].isDirectory()) + { + deleteDirectory(files[i]); + } else + { + files[i].delete(); + } + } + } + return path.delete(); + } + + // helper function for interpreting the configuration data + private void configure() + { + String[] args = preprocessArgs(size); + + int totalTx = this.numberOfTerminals * this.transactionsPerTerminal; + for (int i = 0; i < args.length; i++) + { + if ("-numberOfTerminals".equalsIgnoreCase(args[i])) + { + this.numberOfTerminals = Integer.parseInt(args[++i]); + } else if ("-totalTransactions".equalsIgnoreCase(args[i])) + { + totalTx = Integer.parseInt(args[++i]); + } else if ("-scale".equalsIgnoreCase(args[i])) + { + this.scale = Short.parseShort(args[++i]); + } else if ("-numberOfWarehouses".equalsIgnoreCase(args[i])) + { + this.numberOfWarehouses = Short.parseShort(args[++i]); + } else if ("-createSuffix".equalsIgnoreCase(args[i])) + { + this.createSuffix = args[++i]; + } + } + // calculate the transactions per terminals now that we know the + // total number to be executed and the number of terminals + this.transactionsPerTerminal = totalTx / this.numberOfTerminals; + + System.out.println("number of terminals = " + this.numberOfTerminals); + System.out.println("total transactions = " + + (this.transactionsPerTerminal * this.numberOfTerminals)); + System.out.println("scale = " + this.scale); + System.out.println("number of warehouses = " + this.numberOfWarehouses); + System.out.println("create suffix = " + this.createSuffix); + } + + /************************************************************************************* + * These methods are taken from Benchmark, but should really live on the Config + */ + + // Determine the multi-threading level of this benchmark size. + // TODO refactor Config + private int getThreadCount(String size) + { + switch (config.getThreadModel()) + { + case SINGLE: + return 1; + case FIXED: + return config.getThreadFactor(size); + case PER_CPU: { + int factor = config.getThreadFactor(size); + int cpuCount = Runtime.getRuntime().availableProcessors(); + return factor * cpuCount; + } + default: + throw new RuntimeException("Unknown thread model"); + } + } + + // Retrieve the benchmark arguments for the given size, applying preprocessing + // as appropriate. The preprocessing that is currently done is: + // ${THREADS} - replaced with the specified thread count for the benchmark size + private String[] preprocessArgs(String size) + { + String[] raw = config.getArgs(size); + String[] cooked = new String[raw.length]; + for (int i = 0; i < raw.length; i++) + { + String tmp = raw[i]; + tmp = tmp.replace("${THREADS}", Integer.toString(getThreadCount(size))); + cooked[i] = tmp; + } + return cooked; + } + +} Added: benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/TPCCDataSource.java =================================================================== --- benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/TPCCDataSource.java (rev 0) +++ benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/TPCCDataSource.java 2009-10-21 10:38:25 UTC (rev 569) @@ -0,0 +1,105 @@ +/* + * + */ +package org.dacapo.h2; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.sql.Connection; +import java.sql.Driver; +import java.sql.SQLException; +import java.util.Properties; + +import javax.sql.DataSource; + +/** + * Simple DataSource for providing a wrapped connection for the + * Derby TPC-C to populate the database. + */ +public class TPCCDataSource implements DataSource { + + private final static String USERNAME = "user"; + private final static String PASSWORD = "password"; + private final static String USER = "derby"; + private final static String PASS = "derby"; + + private Driver driver; + private String dbname; + private Properties properties; + private PrintWriter logWriter; + private int loginTimeout = 100; + + public TPCCDataSource(Driver driver, String dbname, Properties properties) { + this.driver = driver; + this.dbname = dbname; + this.properties = properties; + this.logWriter = new PrintWriter(new NullWriter()); + } + + @Override + public Connection getConnection() throws SQLException { + return driver.connect(dbname, properties); + } + + @Override + public Connection getConnection(String username, String password) + throws SQLException { + Properties props = (Properties) properties.clone(); + + props.setProperty(USERNAME, USER); + props.setProperty(PASSWORD, PASS); + + return driver.connect(dbname, properties); + } + + @Override + public PrintWriter getLogWriter() throws SQLException { + return logWriter; + } + + @Override + public int getLoginTimeout() throws SQLException { + return 100; + } + + @Override + public void setLogWriter(PrintWriter logWriter) throws SQLException { + this.logWriter = logWriter; + } + + @Override + public void setLoginTimeout(int loginTimeout) throws SQLException { + this.loginTimeout = loginTimeout; + } + + @Override + public boolean isWrapperFor(Class<?> arg0) throws SQLException { + // TODO Auto-generated method stub + return false; + } + + @Override + public <T> T unwrap(Class<T> arg0) throws SQLException { + // TODO Auto-generated method stub + return null; + } + + private class NullWriter extends Writer { + + @Override + public void close() throws IOException { + } + + @Override + public void flush() throws IOException { + } + + @Override + public void write(char[] arg0, int arg1, int arg2) throws IOException { + } + + }; +} + + Added: benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/TPCCSubmitter.java =================================================================== --- benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/TPCCSubmitter.java (rev 0) +++ benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/h2/TPCCSubmitter.java 2009-10-21 10:38:25 UTC (rev 569) @@ -0,0 +1,53 @@ +/* + * + * Dacapo benchmark harness for TPC-C like workload running on H2. + * + * Apache authored the original TPC-C like workload. + * + * @author Apache + */ +package org.dacapo.h2; + +import org.apache.derbyTesting.system.oe.client.Display; +import org.apache.derbyTesting.system.oe.client.Operations; +import org.apache.derbyTesting.system.oe.client.Submitter; +import org.apache.derbyTesting.system.oe.util.OERandom; + +/** + * A TPC-C like Submitter that will execute a fixed number of transactions + * only counting those transactions that succeed. Failed transactions + * are ignored and another transaction is tried. + */ +public class TPCCSubmitter extends Submitter { + // percentage of transactions that we will tolerate failing + // before giving up as a failed run. + private final static int MAXIMUM_FAILURE_PERCENTAGE = 10; + + public TPCCSubmitter(Display display, Operations ops, OERandom rand, + short maxW) { + super(display, ops, rand, maxW); + } + + @Override + public long runTransactions(final Object displayData, final int count) + throws Exception + { + int failures = 0; + int failure_limit = (count * MAXIMUM_FAILURE_PERCENTAGE)/100; + for (int i = 0; i < count && failures <= failure_limit;) + { + // failed transactions will be ignored an another transaction tried. + try + { + runTransaction(displayData); + i++; + if ((i%50)==0) System.out.print("."); + } catch (Exception e) { + failure_limit++; + } + } + + // timing is done else where + return 0; + } +} Added: benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/harness/H2.java =================================================================== --- benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/harness/H2.java (rev 0) +++ benchmarks/trunk/benchmarks/bms/h2/src/org/dacapo/harness/H2.java 2009-10-21 10:38:25 UTC (rev 569) @@ -0,0 +1,120 @@ +package org.dacapo.harness; + +import java.io.File; +import java.lang.reflect.Method; + +import org.dacapo.harness.Benchmark; +import org.dacapo.parser.Config; + +/** + * Dacapo benchmark harness for TPC-C like workload running on H2. + * + * Apache authored the original TPC-C like workload. + * H2 Group, H2 authored the database H2. + * + * @author Apache + * @author H2 + * + */ +public class H2 extends Benchmark { + + private Object tpcc; + private Method makeTPCC; + private Method prepareTPCC; + private Method preIterationTPCC; + private Method iterationTPCC; + private Method postIterationTPCC; + + public H2(Config config, File scratch) throws Exception { + super(config, scratch); + } + + @Override + protected void prepare() throws Exception { + useBenchmarkClassLoader(); + /* Don't call super.prepare - we don't have a data zip file to unpack */ + try { + Class<?> tpccClazz = Class.forName("org.dacapo.h2.TPCC",true,loader); + this.makeTPCC = tpccClazz.getMethod("make", Config.class, File.class); + this.prepareTPCC = tpccClazz.getMethod("prepare", String.class); + this.preIterationTPCC = tpccClazz.getMethod("preIteration", String.class); + this.iterationTPCC = tpccClazz.getMethod("iteration", String.class); + this.postIterationTPCC = tpccClazz.getMethod("postIteration", String.class); + + // construct the benchmark + this.tpcc = this.makeTPCC.invoke(null, config, scratch); + } finally { + revertClassLoader(); + } + } + + + /** + * The benchmark run + */ + @Override + public void prepare(String size) throws Exception { + useBenchmarkClassLoader(); + try { + this.prepareTPCC.invoke(this.tpcc, size); + } finally { + revertClassLoader(); + } + } + + @Override + public void preIteration(String size) throws Exception { + useBenchmarkClassLoader(); + try { + this.preIterationTPCC.invoke(this.tpcc, size); + } finally { + revertClassLoader(); + } + } + + @Override + public void iterate(String size) throws Exception { + useBenchmarkClassLoader(); + try { + this.iterationTPCC.invoke(this.tpcc, size); + } finally { + revertClassLoader(); + } + } + + @Override + public void postIteration(String size) throws Exception { + useBenchmarkClassLoader(); + try { + this.postIterationTPCC.invoke(this.tpcc, size); + } finally { + revertClassLoader(); + super.postIteration(size); + } + } + + @Override + public void cleanup() { + this.tpcc = null; + this.makeTPCC = null; + this.prepareTPCC = null; + this.preIterationTPCC = null; + this.iterationTPCC = null; + this.postIterationTPCC = null; + + super.cleanup(); + } + + /** + * Stub which exists <b>only</b> to facilitate whole program + * static analysis on a per-benchmark basis. See also the "split-deps" + * ant build target, which is also provided to enable whole program + * static analysis. + * + * @author Eric Bodden + */ + public static void main(String args[]) throws Exception { + // create dummy harness and invoke with dummy arguments + (new H2(null, null)).run(null, ""); + } +} Modified: benchmarks/trunk/benchmarks/build.xml =================================================================== --- benchmarks/trunk/benchmarks/build.xml 2009-10-21 04:44:24 UTC (rev 568) +++ benchmarks/trunk/benchmarks/build.xml 2009-10-21 10:38:25 UTC (rev 569) @@ -27,12 +27,6 @@ 2. Copy default.properties to local.properties and edit local.properties for your environment. - o Specifically, ensure that you have set java14.lib to point to a - Java 1.4 installation and java14.compile.classpath to correctly - capture the libraries for that installation (derby requires 1.4 - libraries at build time). - - 3. Run ant: ant [builds all benchmarks] ant dist [builds all benchmarks, this is the default] @@ -174,7 +168,7 @@ <!-- ================================= target: compile all sources ================================= --> - <target name="compile" depends="avrora,batik,derby,eclipse,fop,jython,luindex,lusearch,pmd,sunflow,tradebeans,tradesoap,tomcat,xalan"> + <target name="compile" depends="avrora,batik,h2,eclipse,fop,jython,luindex,lusearch,pmd,sunflow,tradebeans,tradesoap,tomcat,xalan"> <antcall target="build.status.fail" /> <antcall target="build.status.pass" /> </target> @@ -244,8 +238,8 @@ <target name="batik" depends="init,harness"> <build.bm benchmark="batik"/> </target> - <target name="derby" depends="init,harness"> - <build.bm benchmark="derby"/> + <target name="h2" depends="init,harness"> + <build.bm benchmark="h2"/> </target> <target name="eclipse" depends="init,harness"> <build.bm benchmark="eclipse"/> Added: benchmarks/trunk/benchmarks/libs/derby/build.xml =================================================================== --- benchmarks/trunk/benchmarks/libs/derby/build.xml (rev 0) +++ benchmarks/trunk/benchmarks/libs/derby/build.xml 2009-10-21 10:38:25 UTC (rev 569) @@ -0,0 +1,56 @@ +<project name="derby" default="all" basedir="../.."> + <description>derby library required for h2 testing</description> + <property file="ant/dacapo.properties"/> + + <property name="lib-name" value="derby"/> + <property name="lib-version" value="10.5.3.0"/> + <property name="lib-url" value="${apache.dl.url}/db/derby/db-derby-${lib-version}"/> + <property name="lib-src" value="db-derby-${lib-version}-src.tar.gz"/> + + <import file="../common.xml"/> + + <property name="lib-build-top" value="${lib-build-dir}/db-derby-${lib-version}-src"/> + + <target name="unpack" depends="untar"/> + + <target name="build"> + <copy tofile="${lib-build-top}/tools/java/junit.jar"> + <fileset dir="${basedir}/libs/junit/dist/jar"> + <include name="*.jar"/> + </fileset> + </copy> + <ant antfile="build.xml" inheritall="false" dir="${lib-build-top}"> + <target name="all"/> + <target name="buildjars"/> + </ant> + </target> + + <target name="jar"> + <copy tofile="${derby-jar}" flatten="true"> + <fileset dir="${lib-build-top}"> + <include name="jars/*/derby.jar"/> + </fileset> + </copy> + <copy tofile="${derbyclient-jar}" flatten="true"> + <fileset dir="${lib-build-top}"> + <include name="jars/*/derbyclient.jar"/> + </fileset> + </copy> + <copy tofile="${derbynet-jar}" flatten="true"> + <fileset dir="${lib-build-top}"> + <include name="jars/*/derbynet.jar"/> + </fileset> + </copy> + <copy tofile="${derbytools-jar}" flatten="true"> + <fileset dir="${lib-build-top}"> + <include name="jars/*/derbytools.jar"/> + </fileset> + </copy> + <copy tofile="${derbytesting-jar}" flatten="true"> + <fileset dir="${lib-build-top}"> + <include name="jars/*/derbyTesting.jar"/> + </fileset> + </copy> + </target> + +</project> Added: benchmarks/trunk/benchmarks/libs/derby/downloads/db-derby-10.5.3.0-src.tar.gz.MD5 =================================================================== --- benchmarks/trunk/benchmarks/libs/derby/downloads/db-derby-10.5.3.0-src.tar.gz.MD5 (rev 0) +++ benchmarks/trunk/benchmarks/libs/derby/downloads/db-derby-10.5.3.0-src.tar.gz.MD5 2009-10-21 10:38:25 UTC (rev 569) @@ -0,0 +1 @@ +cffddb994407af2126c5b71affe8fb7f Modified: benchmarks/trunk/benchmarks/libs/libs.xml =================================================================== --- benchmarks/trunk/benchmarks/libs/libs.xml 2009-10-21 04:44:24 UTC (rev 568) +++ benchmarks/trunk/benchmarks/libs/libs.xml 2009-10-21 10:38:25 UTC (rev 569) @@ -37,6 +37,16 @@ <ant antfile="${lib-base}/jdbcbench/build.xml"/> </target> + <!-- derby --> + <property name="derby-jar" value="${lib-base}/derby/dist/jar/derby.jar"/> + <property name="derbyclient-jar" value="${lib-base}/derby/dist/jar/derbyclient.jar"/> + <property name="derbynet-jar" value="${lib-base}/derby/dist/jar/derbynet.jar"/> + <property name="derbytools-jar" value="${lib-base}/derby/dist/jar/derbytools.jar"/> + <property name="derbytesting-jar" value="${lib-base}/derby/dist/jar/derbyTesting.jar"/> + <target name="derby"> + <ant antfile="${lib-base}/derby/build.xml"/> + </target> + <!-- junit --> <property name="junit-jar" value="${lib-base}/junit/dist/jar/junit-3.8.1.jar"/> <target name="junit"> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |