/*
* Date: 08.07.2002
* Time: 19:43:51
*/
package org.apache.ojb.broker;
import org.apache.ojb.broker.query.Criteria;
import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.query.QueryByCriteria;
import org.apache.ojb.broker.util.ObjectModificationDefaultImpl;
import org.apache.ojb.odmg.OJB;
import org.apache.ojb.otm.OTMConnection;
import org.apache.ojb.otm.TestKit;
import org.apache.ojb.otm.lock.LockType;
import org.odmg.DList;
import org.odmg.Database;
import org.odmg.Implementation;
import org.odmg.OQLQuery;
import org.odmg.Transaction;
import java.util.Iterator;
/**
* stress test against one database using several threads
*
* @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>.
* @version $Id: PerformanceTest2.java,v 1.21 2003/09/13 23:50:40 olegnitz Exp $
*/
public class PerformanceTest2 //extends TestCase
{
private TestKit _kit;
private static int iterationsPerThread = 1000;
private static int concurrentThreads = 10;
// used for client generated ids
private static int s_id = 10001;
// if set false, we use autoincrement key gerneration
private static boolean clientKeyGeneration = false;
private static int whichTest = 3;
/**
* times[0] startTime/test length
* times[1] inserting times
* times[2] fetching times
* times[3] deleting times
*/
private long[] times;
private int threadCount;
private String databaseName = TestHelper.DEF_DATABASE_NAME;
/**
* The threads that are executing.
*/
private Thread threads[] = null;
public PerformanceTest2()
{
this.threadCount = concurrentThreads;
_kit = TestKit.getTestInstance();
}
/**
* Interrupt the running threads.
*/
protected void interruptThreads()
{
if (threads != null)
{
for (int i = 0; i < threads.length; i++)
{
threads[i].interrupt();
}
}
System.err.println("## Test failed! ##");
System.err.println("## Test failed! ##");
}
/**
* Run the threads.
*/
protected void runTestClients(final TestClient[] runnables)
{
if (runnables == null)
{
throw new IllegalArgumentException("runnables is null");
}
threads = new Thread[runnables.length];
for (int i = 0; i < threads.length; i++)
{
threads[i] = new Thread(runnables[i]);
}
for (int i = 0; i < threads.length; i++)
{
threads[i].start();
}
try
{
for (int i = 0; i < threads.length; i++)
{
threads[i].join();
}
}
catch (InterruptedException ignore)
{
System.out.println("Thread join interrupted.");
}
threads = null;
}
/**
* generate client made ids
*/
public synchronized static int getId()
{
return ++s_id;
}
public int getArticleCount()
{
Criteria c = new Criteria();
Query q = new QueryByCriteria(PerformanceArticle.class, c);
int count = 0;
try
{
PersistenceBroker broker = PersistenceBrokerFactory.defaultPersistenceBroker();
count = broker.getCount(q);
broker.close();
}
catch (Exception e)
{
e.printStackTrace();
}
return count;
}
public synchronized void addTime(int position, long time)
{
times[position] = times[position] + time;
}
/**
* Setting up the test fixture.
*/
public void init() throws Exception
{
times = new long[4];
threadCount = concurrentThreads;
if ((whichTest & 1) == 1)
{
PerformanceArticle art = createArticle(1000);
PersistenceBroker broker = PersistenceBrokerFactory.defaultPersistenceBroker();
broker.beginTransaction();
broker.store(art);
broker.commitTransaction();
broker.beginTransaction();
broker.delete(art);
broker.commitTransaction();
broker.close();
}
if ((whichTest & 2) == 2)
{
PerformanceArticle art2 = createArticle(1001);
Implementation ojb = OJB.getInstance();
Database db = ojb.newDatabase();
db.open(databaseName, Database.OPEN_READ_WRITE);
Transaction tx = ojb.newTransaction();
tx.begin();
tx.lock(art2, Transaction.WRITE);
tx.commit();
tx.begin();
db.deletePersistent(art2);
tx.commit();
db.close();
}
if ((whichTest & 4) == 4)
{
PerformanceArticle art3 = createArticle(1002);
OTMConnection conn = _kit.acquireConnection(PersistenceBrokerFactory.getDefaultKey());
org.apache.ojb.otm.core.Transaction tx = _kit.getTransaction(conn);
tx.begin();
conn.makePersistent(art3);
tx.commit();
tx = _kit.getTransaction(conn);
tx.begin();
conn.deletePersistent(art3);
tx.commit();
}
}
/**
* factory method that createa an PerformanceArticle
* @return the created PerformanceArticle object
*/
private PerformanceArticle createArticle(int id)
{
PerformanceArticle a = new PerformanceArticle();
if (clientKeyGeneration) a.setArticleId(getId());
a.setArticleName("New Performance Article " + id);
a.setMinimumStock(100);
a.setOrderedUnits(17);
a.setPrice(0.45);
a.setProductGroupId(1);
a.setStock(234);
a.setSupplierId(4);
a.setUnit("bottle");
return a;
}
public static void main(String[] args)
{
int loops = args.length > 4 ? Integer.parseInt(args[4]) : 1;
System.out.println("#######################################" +
"\n### Start stress test - do " + loops + " loop ###" +
"\n#######################################");
for (int i = 0; i < loops; i++)
{
System.out.println("\n## perform loop " + (i + 1) + " ##");
performTest(args);
}
System.exit(0);
}
private static void performTest(String[] args)
{
if (args.length > 0)
{
concurrentThreads = Integer.parseInt(args[0]);
}
if (args.length > 1)
{
iterationsPerThread = Integer.parseInt(args[1]);
}
if (args.length > 2)
{
clientKeyGeneration = Boolean.valueOf(args[2]).booleanValue();
}
if (args.length > 3)
{
whichTest = Integer.parseInt(args[3]);
}
try
{
PerformanceTest2 test = new PerformanceTest2();
int objectCount = 0;
int objectCountAfter = 0;
if ((whichTest & 1) == 1)
{
test.init();
objectCount = test.getArticleCount();
test.testMultithreaded_PB_api();
System.out.println("Test-Info: Objects in DB before PB test: " + objectCount);
objectCountAfter = test.getArticleCount();
System.out.println("Test-Info: Objects in DB after PB test: " + objectCountAfter);
System.out.println("Test-Info: Stress test was successful? - " + (objectCount == objectCountAfter) + " -");
}
if ((whichTest & 2) == 2)
{
test.init();
objectCount = test.getArticleCount();
test.testMultithreaded_ODMG_api();
System.err.println("Test-Info: Objects in DB before ODMG test: " + objectCount);
objectCountAfter = test.getArticleCount();
System.err.println("Test-Info: Objects in DB after ODMG test: " + objectCountAfter);
System.err.println("Test-Info: Stress test was successful? - " + (objectCount == objectCountAfter) + " -");
}
if ((whichTest & 4) == 4)
{
test.init();
objectCount = test.getArticleCount();
test.testMultithreaded_OTM_api();
System.err.println("Test-Info: Objects in DB before OTM test: " + objectCount);
objectCountAfter = test.getArticleCount();
System.err.println("Test-Info: Objects in DB after OTM test: " + objectCountAfter);
System.err.println("Test-Info: Stress test was successful? - " + (objectCount == objectCountAfter) + " -");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void testMultithreaded_PB_api()
{
String sep = System.getProperty("line.separator");
System.out.println(sep + sep + "++ Start thread generation for PB api test ++");
System.out.println("Begin with performance test, " + concurrentThreads +
" concurrent threads, handle " + iterationsPerThread + " articles per thread");
PerfomanceTestClientPB[] clientsPB = new PerfomanceTestClientPB[concurrentThreads];
for (int i = 0; i < concurrentThreads; i++)
{
PerfomanceTestClientPB obj = new PerfomanceTestClientPB(this);
clientsPB[i] = obj;
}
System.out.println("");
times[0] = System.currentTimeMillis();
runTestClients(clientsPB);
times[0] = (long) (System.currentTimeMillis() - times[0]);
System.out.println(buildTestSummary("PB API"));
System.out.println("++ End of performance test PB api ++" + sep + sep);
}
public void testMultithreaded_ODMG_api()
{
String sep = System.getProperty("line.separator");
System.out.println("++ Start thread generation for ODMG api test ++");
System.out.println("Begin with performance test, " + concurrentThreads +
" concurrent threads, handle " + iterationsPerThread + " articles per thread");
PerfomanceTestClientODMG[] clientsODMG = new PerfomanceTestClientODMG[concurrentThreads];
for (int i = 0; i < concurrentThreads; i++)
{
PerfomanceTestClientODMG obj = new PerfomanceTestClientODMG(this);
clientsODMG[i] = obj;
}
System.out.println("");
times[0] = System.currentTimeMillis();
runTestClients(clientsODMG);
times[0] = (long) (System.currentTimeMillis() - times[0]);
System.out.println(buildTestSummary("ODMG"));
System.out.println("++ End of performance test ODMG api ++" + sep);
}
public void testMultithreaded_OTM_api()
{
String sep = System.getProperty("line.separator");
System.out.println("++ Start thread generation for OTM api test ++");
System.out.println("Begin with performance test, " + concurrentThreads +
" concurrent threads, handle " + iterationsPerThread + " articles per thread");
PerfomanceTestClientOTM[] clientsOTM = new PerfomanceTestClientOTM[concurrentThreads];
for (int i = 0; i < concurrentThreads; i++)
{
PerfomanceTestClientOTM obj = new PerfomanceTestClientOTM(this);
clientsOTM[i] = obj;
}
System.out.println("");
times[0] = System.currentTimeMillis();
runTestClients(clientsOTM);
times[0] = (long) (System.currentTimeMillis() - times[0]);
System.out.println(buildTestSummary("OTM"));
System.out.println("++ End of performance test OTM api ++" + sep);
}
private String buildTestSummary(String key)
{
String sep = System.getProperty("line.separator");
StringBuffer buf = new StringBuffer();
buf.append(sep);
buf.append("----------------------------------------------------");
buf.append(sep);
buf.append("TEST SUMMARY - " + key);
buf.append(sep);
buf.append(concurrentThreads + " concurrent threads, handle " + iterationsPerThread + " articles per thread");
buf.append(sep);
buf.append("Test period: " + (double) (((double) times[0]) / 1000) + " [sec]");
buf.append(sep);
buf.append("Inserting period: " + (times[1] / (concurrentThreads)) + " [msec]");
buf.append(sep);
buf.append("Fetching period: " + (times[2] / (concurrentThreads)) + " [msec]");
buf.append(sep);
buf.append("Deleting period: " + (times[3] / (concurrentThreads)) + " [msec]");
buf.append(sep);
buf.append("----------------------------------------------------");
return buf.toString();
}
abstract class TestClient implements Runnable
{
}
/**
* ODMG-api test class
*/
class PerfomanceTestClientODMG extends TestClient
{
private static final String PRE_NAME = "A_";
private PerformanceArticle[] arr;
private Implementation odmg;
private String threadName;
private Database m_db;
private PerformanceTest2 test;
public PerfomanceTestClientODMG(PerformanceTest2 test)
{
this.test = test;
}
public void run()
{
odmg = OJB.getInstance();
threadName = Thread.currentThread().toString();
arr = new PerformanceArticle[iterationsPerThread];
for (int i = 0; i < iterationsPerThread; i++)
{
PerformanceArticle a = createArticle(i, threadName);
arr[i] = a;
}
try
{
insertNewArticles();
readArticlesByCursor();
deleteArticles();
}
catch (Throwable e)
{
System.out.println("Error in client " + this);
e.printStackTrace();
test.interruptThreads();
}
}
/**
* factory method that createa an PerformanceArticle
* @return the created PerformanceArticle object
*/
private PerformanceArticle createArticle(int id, String name)
{
PerformanceArticle a = new PerformanceArticle();
if (clientKeyGeneration) a.setArticleId(getId());
a.setArticleName(PRE_NAME + name);
a.setMinimumStock(100);
a.setOrderedUnits(17);
a.setPrice(0.45);
a.setProductGroupId(1);
a.setStock(234);
a.setSupplierId(4);
a.setUnit("bottle");
return a;
}
protected void deleteArticles() throws Exception
{
long start = System.currentTimeMillis();
Database db = odmg.newDatabase();
db.open(databaseName, Database.OPEN_READ_WRITE);
Transaction tx = odmg.newTransaction();
tx.begin();
for (int i = 0; i < arr.length; i++)
{
db.deletePersistent(arr[i]);
}
tx.commit();
db.close();
long stop = System.currentTimeMillis();
times[3] = times[3] + (stop - start);
}
protected void insertNewArticles() throws Exception
{
long start = System.currentTimeMillis();
Database db = odmg.newDatabase();
db.open(databaseName, Database.OPEN_READ_WRITE);
Transaction tx = odmg.newTransaction();
tx.begin();
for (int i = 0; i < arr.length; i++)
{
tx.lock(arr[i], Transaction.WRITE);
}
tx.commit();
db.close();
long stop = System.currentTimeMillis();
times[1] = times[1] + (stop - start);
}
protected void readArticlesByCursor() throws Exception
{
long start = System.currentTimeMillis();
int artId = arr[0].articleId;
Database db = odmg.newDatabase();
db.open(databaseName, Database.OPEN_READ_WRITE);
// for better performance we could read without a tx
// Transaction tx = ojb.newTransaction();
// tx.begin();
OQLQuery query = odmg.newOQLQuery();
String sql = "select allArticles from " + PerformanceArticle.class.getName() +
" where articleName = \"" + PRE_NAME + threadName + "\"";
query.create(sql);
DList allProducts = (DList) query.execute();
// tx.commit();
Iterator iter = allProducts.iterator();
int fetchCount = 0;
while (iter.hasNext())
{
fetchCount++;
PerformanceArticle a = (PerformanceArticle) iter.next();
}
db.close();
long stop = System.currentTimeMillis();
times[2] = times[2] + (stop - start);
}
}
/**
* OTM-api test class
*/
class PerfomanceTestClientOTM extends TestClient
{
private PerformanceArticle[] arr;
private String threadName;
private PerformanceTest2 test;
public PerfomanceTestClientOTM(PerformanceTest2 test)
{
this.test = test;
}
public void run()
{
threadName = Thread.currentThread().toString();
arr = new PerformanceArticle[iterationsPerThread];
for (int i = 0; i < iterationsPerThread; i++)
{
PerformanceArticle a = createArticle(i, threadName);
arr[i] = a;
}
try
{
OTMConnection conn = _kit.acquireConnection(PersistenceBrokerFactory.getDefaultKey());
insertNewArticles(conn);
readArticlesByCursor(conn);
deleteArticles(conn);
conn.close();
}
catch (Throwable e)
{
System.out.println("Error in client " + this);
e.printStackTrace();
test.interruptThreads();
}
}
/**
* factory method that createa an PerformanceArticle
* @return the created PerformanceArticle object
*/
private PerformanceArticle createArticle(int id, String name)
{
PerformanceArticle a = new PerformanceArticle();
if (clientKeyGeneration) a.setArticleId(getId());
a.setArticleName("New Performance Article " + id);
a.setMinimumStock(100);
a.setOrderedUnits(17);
a.setPrice(0.45);
a.setProductGroupId(1);
a.setStock(234);
a.setSupplierId(4);
a.setUnit("bottle");
return a;
}
protected void deleteArticles(OTMConnection conn) throws Exception
{
long start = System.currentTimeMillis();
org.apache.ojb.otm.core.Transaction tx = _kit.getTransaction(conn);
tx.begin();
for (int i = 0; i < arr.length; i++)
{
conn.deletePersistent(arr[i]);
}
tx.commit();
long stop = System.currentTimeMillis();
times[3] = times[3] + (stop - start);
}
protected void insertNewArticles(OTMConnection conn) throws Exception
{
long start = System.currentTimeMillis();
org.apache.ojb.otm.core.Transaction tx = _kit.getTransaction(conn);
tx.begin();
for (int i = 0; i < arr.length; i++)
{
conn.makePersistent(arr[i]);
}
tx.commit();
long stop = System.currentTimeMillis();
times[1] = times[1] + (stop - start);
}
protected void readArticlesByCursor(OTMConnection conn) throws Exception
{
long start = System.currentTimeMillis();
int artId = arr[0].articleId;
org.apache.ojb.otm.core.Transaction tx = _kit.getTransaction(conn);
Criteria c = new Criteria();
c.addBetween("articleId", new Integer(artId), new Integer(artId + iterationsPerThread));
Query q = new QueryByCriteria(PerformanceArticle.class, c);
Iterator iter = conn.getIteratorByQuery(q, LockType.NO_LOCK);
int fetchCount = 0;
while (iter.hasNext())
{
fetchCount++;
PerformanceArticle a = (PerformanceArticle) iter.next();
}
long stop = System.currentTimeMillis();
times[2] = times[2] + (stop - start);
}
}
/**
* PB-api test class
*/
class PerfomanceTestClientPB extends TestClient
{
private PerformanceArticle[] arr;
private PerformanceTest2 test;
public PerfomanceTestClientPB(PerformanceTest2 test)
{
this.test = test;
arr = new PerformanceArticle[iterationsPerThread];
for (int i = 0; i < iterationsPerThread; i++)
{
PerformanceArticle a = createArticle(i);
arr[i] = a;
}
}
public void run()
{
try
{
insertNewArticles();
readArticlesByCursor();
deleteArticles();
}
catch (Throwable e)
{
System.out.println("Error in client " + this);
e.printStackTrace();
test.interruptThreads();
}
}
/**
* factory method that createa an PerformanceArticle
* @return the created PerformanceArticle object
*/
private PerformanceArticle createArticle(int id)
{
PerformanceArticle a = new PerformanceArticle();
if (clientKeyGeneration) a.setArticleId(getId());
a.setArticleName("New Performance Article " + id);
a.setMinimumStock(100);
a.setOrderedUnits(17);
a.setPrice(0.45);
a.setProductGroupId(1);
a.setStock(234);
a.setSupplierId(4);
a.setUnit("bottle");
return a;
}
protected void deleteArticles() throws Exception
{
long start = System.currentTimeMillis();
for (int i = 0; i < arr.length; i++)
{
PersistenceBroker broker = null;
try
{
broker = PersistenceBrokerFactory.defaultPersistenceBroker();
broker.beginTransaction();
broker.delete(arr[i]);
broker.commitTransaction();
}
finally
{
if (broker != null) broker.close();
}
}
long stop = System.currentTimeMillis();
times[3] = times[3] + (stop - start);
}
protected void insertNewArticles() throws Exception
{
ObjectModificationDefaultImpl needsInsert = new ObjectModificationDefaultImpl();
needsInsert.setNeedsInsert(true);
long start = System.currentTimeMillis();
for (int i = 0; i < arr.length; i++)
{
PersistenceBroker broker = null;
try
{
broker = PersistenceBrokerFactory.defaultPersistenceBroker();
broker.beginTransaction();
broker.store(arr[i], needsInsert);
broker.commitTransaction();
}
finally
{
if (broker != null) broker.close();
}
}
long stop = System.currentTimeMillis();
times[1] = times[1] + (stop - start);
}
protected void readArticlesByCursor() throws Exception
{
long start = System.currentTimeMillis();
int artId = arr[0].articleId;
Criteria c = new Criteria();
c.addBetween("articleId", new Integer(artId), new Integer(artId + iterationsPerThread));
Query q = new QueryByCriteria(PerformanceArticle.class, c);
PersistenceBroker broker = null;
try
{
broker = PersistenceBrokerFactory.defaultPersistenceBroker();
Iterator iter = broker.getIteratorByQuery(q);
int fetchCount = 0;
while (iter.hasNext())
{
fetchCount++;
PerformanceArticle a = (PerformanceArticle) iter.next();
}
}
finally
{
if (broker != null) broker.close();
}
long stop = System.currentTimeMillis();
times[2] = times[2] + (stop - start);
}
}
}