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 rh...@apache.org on 2010/03/04 21:17:54 UTC

svn commit: r919159 - /db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/

Author: rhillegas
Date: Thu Mar  4 20:17:54 2010
New Revision: 919159

URL: http://svn.apache.org/viewvc?rev=919159&view=rev
Log:
DERBY-4565: Add a client for testing the concurrency of sequence generators.

Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SequenceGeneratorConcurrency.java   (with props)
Modified:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BankTransactionClient.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/GroupByClient.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java

Modified: 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=919159&r1=919158&r2=919159&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java Thu Mar  4 20:17:54 2010
@@ -52,6 +52,8 @@
             client = c;
         }
 
+        public Client getClient() { return client; }
+
         public void run() {
             try {
                 while (!stop) {
@@ -128,5 +130,10 @@
         out.println("Test duration (s):\t" + ((double) time / 1000));
         out.println("Number of transactions:\t" + count);
         out.println("Average throughput (tx/s):\t" + tps);
+        
+        for (int i = 0; i < threads.length; i++)
+        {
+            threads[i].getClient().printReport( out );
+        }
     }
 }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BankTransactionClient.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BankTransactionClient.java?rev=919159&r1=919158&r2=919159&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BankTransactionClient.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BankTransactionClient.java Thu Mar  4 20:17:54 2010
@@ -21,6 +21,7 @@
 
 package org.apache.derbyTesting.perf.clients;
 
+import java.io.PrintStream;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -165,6 +166,8 @@
         conn.commit();
     }
 
+    public void printReport(PrintStream out) {}
+    
     /**
      * Generate a random teller id.
      */

Modified: 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=919159&r1=919158&r2=919159&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java Thu Mar  4 20:17:54 2010
@@ -21,6 +21,7 @@
 
 package org.apache.derbyTesting.perf.clients;
 
+import java.io.PrintStream;
 import java.sql.Connection;
 import java.sql.SQLException;
 
@@ -47,4 +48,11 @@
      * @throws SQLException if a database error occurs
      */
     void doWork() throws SQLException;
+    
+    /**
+     * Print a report from the test run.
+     *
+     * @param out stream to print the report to
+     */
+    void printReport(PrintStream out);
 }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/GroupByClient.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/GroupByClient.java?rev=919159&r1=919158&r2=919159&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/GroupByClient.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/GroupByClient.java Thu Mar  4 20:17:54 2010
@@ -21,6 +21,7 @@
 
 package org.apache.derbyTesting.perf.clients;
 
+import java.io.PrintStream;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.Statement;
@@ -214,4 +215,6 @@
         conn.commit();
     }
 
+    public void printReport(PrintStream out) {}
+    
 }

Modified: 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=919159&r1=919158&r2=919159&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java Thu Mar  4 20:17:54 2010
@@ -21,6 +21,7 @@
 
 package org.apache.derbyTesting.perf.clients;
 
+import java.io.PrintStream;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
@@ -52,4 +53,6 @@
         conn.commit();
     }
 
+    public void printReport(PrintStream out) {}
+    
 }

Modified: 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=919159&r1=919158&r2=919159&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java Thu Mar  4 20:17:54 2010
@@ -70,6 +70,8 @@
             client = c;
         }
 
+        public Client getClient() { return client; }
+
         /**
          * Tell the client to stop waiting.
          */
@@ -195,5 +197,10 @@
         out.println("Average response time (ms):\t" + avgResp);
         out.println("Minimum response time (ms):\t" + min);
         out.println("Maximum response time (ms):\t" + max);
+        
+        for (int i = 0; i < threads.length; i++)
+        {
+            threads[i].getClient().printReport( out );
+        }
     }
 }

Modified: 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=919159&r1=919158&r2=919159&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java Thu Mar  4 20:17:54 2010
@@ -244,6 +244,12 @@
 "              in the database has (default: 10)\n" +
 "            - accountsPerBranch=NN: specifies the number of accounts in\n" +
 "              each branch (default: 100000)\n" +
+"      * seq_gen - sequence generator concurrency. Accepts\n" +
+"                    the following load-specific options (see also -load_opts):\n" +
+"            - numberOfGenerators: number of sequences to create\n" +
+"            - tablesPerGenerator: number of tables to create per sequence\n" +
+"            - insertsPerTransaction: number of inserts to perform per transaction\n" +
+"            - debugging: 1 means print debug chatter, 0 means do not print the chatter\n" +
 "  -load_opts: comma-separated list of load-specific options\n" +
 "  -gen: load generator, default: b2b, valid types:\n" +
 "      * b2b - clients perform operations back-to-back\n" +
@@ -311,6 +317,8 @@
                 getLoadOpt("branches", 1),
                 getLoadOpt("tellersPerBranch", 10),
                 getLoadOpt("accountsPerBranch", 100000));
+        } else if (load.equals("seq_gen")) {
+            return new SequenceGeneratorConcurrency.Filler();
         }
         System.err.println("unknown load: " + load);
         printUsage(System.err);
@@ -347,6 +355,8 @@
                 getLoadOpt("branches", 1),
                 getLoadOpt("tellersPerBranch", 10),
                 getLoadOpt("accountsPerBranch", 100000));
+        } else if (load.equals("seq_gen")) {
+            return new SequenceGeneratorConcurrency.SGClient();
         }
         System.err.println("unknown load: " + load);
         printUsage(System.err);

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SequenceGeneratorConcurrency.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SequenceGeneratorConcurrency.java?rev=919159&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SequenceGeneratorConcurrency.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SequenceGeneratorConcurrency.java Thu Mar  4 20:17:54 2010
@@ -0,0 +1,326 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.SequenceGeneratorConcurrency
+
+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.PreparedStatement;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Random;
+
+/**
+ * <p>
+ * Machinery to test the concurrency of sequence generators.
+ * </p>
+ */
+public class SequenceGeneratorConcurrency
+{
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // LOAD OPTIONS FOR THIS TEST
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * <p>
+     * Describes the load options specific to a run of the SequenceGeneratorConcurrency test.
+     * </p>
+     */
+    public static final class LoadOptions
+    {
+        private int _numberOfGenerators;
+        private int _tablesPerGenerator;
+        private int _insertsPerTransaction;
+        private boolean _debugging;
+
+        public LoadOptions()
+        {
+            _numberOfGenerators = Runner.getLoadOpt( "numberOfGenerators", 1 );
+            _tablesPerGenerator = Runner.getLoadOpt( "tablesPerGenerator", 1 );
+            _insertsPerTransaction = Runner.getLoadOpt( "insertsPerTransaction", 1 );
+            _debugging = ( Runner.getLoadOpt( "debugging", 0 ) == 1 );
+        }
+
+        /** Get the number of generators created by this test run */
+        public int getNumberOfGenerators() { return _numberOfGenerators; }
+
+        /** Get the number of tables created for each generator */
+        public int getTablesPerGenerator() { return _tablesPerGenerator; }
+
+        /** Get the number of inserts performed per transaction */
+        public int getInsertsPerTransaction() { return _insertsPerTransaction; }
+
+        /** Return whether we are in debugging mode */
+        public boolean debugging() { return _debugging; }
+
+        public String toString()
+        {
+            StringBuffer buffer = new StringBuffer();
+
+            buffer.append( "LoadOptions( " );
+            buffer.append( " generators = " + _numberOfGenerators );
+            buffer.append( ", tablesPerGenerator = " + _tablesPerGenerator );
+            buffer.append( ", insertsPerTransaction = " + _insertsPerTransaction );
+            buffer.append( ", debugging = " + _debugging );
+            buffer.append( " )" );
+
+            return buffer.toString();
+        }
+        
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // DBFiller IMPLEMENTATION
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * <p>
+     * Create the schema necessary to support this test run.
+     * </p>
+     */
+    public static final class Filler implements DBFiller
+    {
+        private LoadOptions _loadOptions;
+
+        public Filler()
+        {
+            _loadOptions = new LoadOptions();
+        }
+
+        public void fill( Connection conn ) throws SQLException
+        {
+            int numberOfGenerators = _loadOptions.getNumberOfGenerators();
+            int tablesPerGenerator = _loadOptions.getTablesPerGenerator();
+
+            for ( int sequence = 0; sequence < numberOfGenerators; sequence++ )
+            {
+                runDDL( conn, "create sequence " + makeSequenceName( sequence ) );
+
+                for ( int table = 0; table < tablesPerGenerator; table++ )
+                {
+                    runDDL( conn, "create table " + makeTableName( sequence, table ) + "( a int )" );
+                }
+            }
+        }
+
+        /** Run a DDL statement */
+        private void runDDL( Connection conn, String ddl ) throws SQLException
+        {
+            PreparedStatement ps = prepareStatement( conn, _loadOptions.debugging(), ddl );
+            ps.execute();
+            ps.close();
+        }
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // Client IMPLEMENTATION
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    public static final class SGClient implements Client
+    {
+        private LoadOptions _loadOptions;
+        private Connection _conn;
+        private PreparedStatement _psArray[][];
+        private Random _randomNumberGenerator;
+        private int _clientNumber;
+        private int _transactionCount;
+        private int _errorCount = 0;
+        private HashMap _errorLog;
+
+        private static int _clientCount = 0;
+
+        // filled in at reporting time
+        private static int _totalErrorCount = 0;
+        private static int _totalTransactionCount = 0;
+
+        public SGClient()
+        {
+            _clientNumber = _clientCount++;
+            _transactionCount = 0;
+            _errorLog = new HashMap();
+            _loadOptions = new LoadOptions();
+
+            _psArray = new PreparedStatement[ _loadOptions.getNumberOfGenerators() ] [ _loadOptions.getTablesPerGenerator() ];
+            _randomNumberGenerator = new Random();
+
+            if ( _loadOptions.debugging() )
+            {
+                debugPrint( "Creating client " + _clientNumber + " with " + _loadOptions.toString() );
+            }
+        }
+
+        /** Create the PreparedStatements needed by the test run. */
+        public void init( Connection conn ) throws SQLException
+        {
+            _conn = conn;
+
+            int numberOfGenerators = _loadOptions.getNumberOfGenerators();
+            int tablesPerGenerator = _loadOptions.getTablesPerGenerator();
+            boolean debugging = _loadOptions.debugging();
+
+            for ( int sequence = 0; sequence < numberOfGenerators; sequence++ )
+            {
+                String sequenceName = makeSequenceName( sequence );
+
+                for ( int table = 0; table < tablesPerGenerator; table++ )
+                {
+                    String tableName = makeTableName( sequence, table );
+                    
+                    _psArray[ sequence ][ table ] = prepareStatement
+                        ( _conn, debugging, "insert into " + tableName + "( a ) values ( next value for " + sequenceName + " )" );
+                }
+            }
+
+            _conn.setAutoCommit( false );
+        }
+
+        /** A transaction performed by this thread */
+        public void doWork() throws SQLException
+        {
+            int sequence = getPositiveRandomNumber() % _loadOptions.getNumberOfGenerators();
+            int table = getPositiveRandomNumber() % _loadOptions.getTablesPerGenerator();
+            int insertsPerTransaction = _loadOptions.getInsertsPerTransaction();
+            boolean debugging = _loadOptions.debugging();
+
+            int rowNumber = 0;
+
+            try {
+                for ( ; rowNumber < insertsPerTransaction; rowNumber++ )
+                {
+                    _psArray[ sequence ][ table ].executeUpdate();
+                }
+            }
+            catch (SQLException t)
+            {
+                debugPrint
+                    (
+                     "Error on client " + _clientNumber +
+                     " on sequence " + sequence +
+                     " in transaction " + _transactionCount +
+                     " on row " + rowNumber
+                     );
+
+                addError( t );
+                _conn.rollback();
+
+                return;
+            }
+
+            _conn.commit();
+            
+            _transactionCount++;
+        }
+
+        private int getPositiveRandomNumber()
+        {
+            int raw = _randomNumberGenerator.nextInt();
+
+            if ( raw < 0 ) { return -raw; }
+            else { return raw; }
+        }
+
+        public void printReport(PrintStream out)
+        {
+            Iterator keyIterator = _errorLog.keySet().iterator();
+
+            while ( keyIterator.hasNext() )
+            {
+                String key = (String) keyIterator.next();
+                int[] value = (int[]) _errorLog.get( key );
+
+                String message = "    Client " + _clientNumber + " saw " + value[0] + " instances of this error: " + key;
+
+                out.println( message );
+            }
+
+            _totalErrorCount += _errorCount;
+            _totalTransactionCount += _transactionCount;
+
+            // last client reports the totals
+            if ( _clientNumber == ( _clientCount - 1 ) )
+            {
+                out.println( "\n" );
+                out.println( _loadOptions.toString() );
+                out.println( _totalErrorCount + " errors, including warmup phase." );
+                out.println( _totalTransactionCount + " successful transactions, including warmup phase." );
+            }
+        }
+        
+        // error management
+
+        /** Bump the error count for this problem */
+        private void addError( Throwable t )
+        {
+            _errorCount++;
+            
+            String key = t.getClass().getName() + ": " + t.getMessage();
+            int[] value = (int[]) _errorLog.get( key );
+
+            if ( value != null ) { value[ 0 ] = value[ 0 ] + 1; }
+            else
+            {
+                _errorLog.put( key, new int[] { 1 } );
+            }
+        }
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // UTILITY METHODS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /** make the name of a sequence */
+    public static String makeSequenceName( int sequence )
+    { return "seq_" + sequence; }
+    
+    /** make the name of a table */
+    public static String makeTableName( int sequence, int table )
+    { return "t_" + sequence + "_" + table; }
+
+    public static PreparedStatement prepareStatement
+        ( Connection conn, boolean debugging, String text ) throws SQLException
+    {
+        if ( debugging ) { debugPrint( text ); }
+
+        return conn.prepareStatement( text );
+    }
+    
+    public static void debugPrint( String text )
+    {
+        print( "DEBUG: " + text );
+    }
+
+    public static void print( String text )
+    {
+        System.out.println( text );
+    }
+
+}
+
+

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SequenceGeneratorConcurrency.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 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=919159&r1=919158&r2=919159&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java Thu Mar  4 20:17:54 2010
@@ -21,6 +21,7 @@
 
 package org.apache.derbyTesting.perf.clients;
 
+import java.io.PrintStream;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -114,6 +115,8 @@
         conn.commit();
     }
 
+    public void printReport(PrintStream out) {}
+    
     /**
      * Make sure the text column is retrieved and read. Different methods
      * are used for the retrieval based on whether the column is a VARCHAR,

Modified: 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=919159&r1=919158&r2=919159&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java Thu Mar  4 20:17:54 2010
@@ -22,6 +22,7 @@
 package org.apache.derbyTesting.perf.clients;
 
 import java.io.ByteArrayInputStream;
+import java.io.PrintStream;
 import java.io.StringReader;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
@@ -116,4 +117,6 @@
         conn.commit();
     }
 
+    public void printReport(PrintStream out) {}
+    
 }