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.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 different databases with serveral threads
*
* @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>.
*/
public class PerformanceTest3
{
private static String databaseNameFarAway = TestHelper.FAR_AWAY_DATABASE_NAME;
private static PBKey pbKey_FarAway = TestHelper.FAR_AWAY_KEY;
private static String databaseName = TestHelper.DEF_DATABASE_NAME;
private static PBKey pbKey = TestHelper.DEF_KEY;
private static int iterationsPerThread = 1000;
private static int concurrentThreads = 10;
//used for client generated ids
private static int s_id = 10001;
private static int whichTest = 3;
private static boolean clientKeyGeneration = false;
/**
* times[0] startTime/test length
* times[1] inserting times
* times[2] fetching times
* times[3] deleting times
*/
private long[] times;
private int threadCount;
public ThreadGroup threadGroup = new ThreadGroup("PerfTest");
/**
* The threads that are executing.
*/
private Thread threads[] = null;
public PerformanceTest3()
{
this.threadCount = concurrentThreads;
}
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
{
PerformanceTest3 test = new PerformanceTest3();
int objectCountDefault = 0;
int objectCountDefaultAfter = 0;
int objectCountFarAway = 0;
int objectCountFarAwayAfter = 0;
if (whichTest == 1 || whichTest == 3)
{
test.init();
objectCountDefault = test.getArticleCount();
objectCountFarAway = test.getFarAwayCount();
test.testMultithreaded_PB_api();
System.err.println("Test-Info: Objects in default DB before PB test: " + objectCountDefault);
objectCountDefaultAfter = test.getArticleCount();
System.err.println("Test-Info: Objects in default DB after PB test: " + objectCountDefaultAfter);
System.err.println("Test-Info: Objects in farAway_DB before PB test: " + objectCountFarAway);
objectCountFarAwayAfter = test.getFarAwayCount();
System.err.println("Test-Info: Objects in farAway_DB after PB test: " + objectCountFarAwayAfter);
System.err.println("Test-Info: Stress test was successful? - " +
(objectCountDefault == objectCountDefaultAfter && (objectCountFarAway == objectCountFarAwayAfter)) + " -");
}
if (whichTest == 2 || whichTest == 3)
{
test.init();
objectCountDefault = test.getArticleCount();
objectCountFarAway = test.getFarAwayCount();
test.testMultithreaded_ODMG_api();
System.err.println("Test-Info: Objects in default DB before ODMG test: " + objectCountDefault);
objectCountDefaultAfter = test.getArticleCount();
System.err.println("Test-Info: Objects in default DB after ODMG test: " + objectCountDefaultAfter);
System.err.println("Test-Info: Objects in farAway_DB before ODMG test: " + objectCountFarAway);
objectCountFarAwayAfter = test.getFarAwayCount();
System.err.println("Test-Info: Objects in farAway_DB after ODMG test: " + objectCountFarAwayAfter);
System.err.println("Test-Info: Stress test was successful? - " +
(objectCountDefault == objectCountDefaultAfter && (objectCountFarAway == objectCountFarAwayAfter)) + " -");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* 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;
}
public synchronized void addTime(int position, long time)
{
times[position] = times[position] + time;
}
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);
}
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
{
}
//*******************************************************************************************************
// Inner class ODMG test client
//*******************************************************************************************************
/**
* ODMG-api test class
*/
class PerfomanceTestClientODMG extends TestClient
{
private PerformanceArticle[] arr;
private FarAwayClass[] arrFarAway;
private Implementation ojb;
private static final String PRE_NAME = "A_";
private String threadName;
private PerformanceTest3 test;
public PerfomanceTestClientODMG(PerformanceTest3 test)
{
this.test = test;
}
public void run()
{
ojb = OJB.getInstance();
threadName = Thread.currentThread().getName();
arr = new PerformanceArticle[iterationsPerThread];
for (int i = 0; i < iterationsPerThread; i++)
{
PerformanceArticle a = createArticle(i, threadName);
arr[i] = a;
}
arrFarAway = new FarAwayClass[iterationsPerThread];
for (int i = 0; i < iterationsPerThread; i++)
{
FarAwayClass a = createFarAwayObject(i, threadName);
arrFarAway[i] = a;
}
//log.info("Thread "+this+" run");
try
{
insertNewArticles();
readArticlesByCursor();
deleteArticles();
insertNewFarAways();
readFarAwaysByCursor();
deleteFarAways();
}
catch (Throwable e)
{
e.printStackTrace();
System.err.println("Error in client " + this);
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;
}
private FarAwayClass createFarAwayObject(int i, String name)
{
FarAwayClass fa = new FarAwayClass();
if (clientKeyGeneration) fa.setId(getId());
fa.setName(PRE_NAME + name);
fa.setDescription("so far away from " + i);
return fa;
}
protected void deleteArticles() throws Exception
{
long start = System.currentTimeMillis();
Database db = ojb.newDatabase();
db.open(databaseName, Database.OPEN_READ_WRITE);
for (int i = 0; i < arr.length; i++)
{
Transaction tx = ojb.newTransaction();
tx.begin();
db.deletePersistent(arr[i]);
tx.commit();
}
db.close();
long stop = System.currentTimeMillis();
times[3] = times[3] + (stop - start);
}
protected void deleteFarAways() throws Exception
{
long start = System.currentTimeMillis();
Database db = ojb.newDatabase();
db.open(databaseNameFarAway, Database.OPEN_READ_WRITE);
for (int i = 0; i < arr.length; i++)
{
Transaction tx = ojb.newTransaction();
tx.begin();
db.deletePersistent(arrFarAway[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 = ojb.newDatabase();
db.open(databaseName, Database.OPEN_READ_WRITE);
for (int i = 0; i < arr.length; i++)
{
Transaction tx = ojb.newTransaction();
tx.begin();
tx.lock(arr[i], Transaction.WRITE);
tx.commit();
}
db.close();
long stop = System.currentTimeMillis();
times[1] = times[1] + (stop - start);
}
protected void insertNewFarAways() throws Exception
{
long start = System.currentTimeMillis();
Database db = ojb.newDatabase();
db.open(databaseNameFarAway, Database.OPEN_READ_WRITE);
for (int i = 0; i < arr.length; i++)
{
Transaction tx = ojb.newTransaction();
tx.begin();
tx.lock(arrFarAway[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 = ojb.newDatabase();
db.open(databaseName, Database.OPEN_READ_WRITE);
Transaction tx = ojb.newTransaction();
tx.begin();
OQLQuery query = ojb.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);
}
protected void readFarAwaysByCursor() throws Exception
{
long start = System.currentTimeMillis();
int farAway_id = arrFarAway[0].getId();
Database db = ojb.newDatabase();
db.open(databaseNameFarAway, Database.OPEN_READ_WRITE);
Transaction tx = ojb.newTransaction();
tx.begin();
OQLQuery query = ojb.newOQLQuery();
String sql = "select allFarAways from " + FarAwayClass.class.getName() +
" where name = \"" + PRE_NAME + threadName + "\"";
query.create(sql);
DList allFarAways = (DList) query.execute();
tx.commit();
Iterator iter = allFarAways.iterator();
int fetchCount = 0;
while (iter.hasNext())
{
fetchCount++;
FarAwayClass a = (FarAwayClass) iter.next();
}
db.close();
long stop = System.currentTimeMillis();
times[2] = times[2] + (stop - start);
}
}
//*******************************************************************************************************
// Inner class PB test client
//*******************************************************************************************************
/**
* PB-api test class
*/
class PerfomanceTestClientPB extends TestClient
{
private PerformanceArticle[] arr;
private FarAwayClass[] arrFarAway;
private Implementation ojb;
private PerformanceTest3 test;
public PerfomanceTestClientPB(PerformanceTest3 test)
{
this.test = test;
ojb = OJB.getInstance();
arr = new PerformanceArticle[iterationsPerThread];
for (int i = 0; i < iterationsPerThread; i++)
{
PerformanceArticle a = createArticle(i);
arr[i] = a;
}
arrFarAway = new FarAwayClass[iterationsPerThread];
for (int i = 0; i < iterationsPerThread; i++)
{
FarAwayClass a = createFarAwayObject(i);
arrFarAway[i] = a;
}
//log.info("Articles created");
}
public void run()
{
//log.info("Thread "+this+" run");
try
{
insertNewFarAways();
insertNewArticles();
readArticlesByCursor();
readFarAwaysByCursor();
deleteArticles();
deleteFarAways();
}
catch (Throwable e)
{
e.printStackTrace();
System.err.println("Error in client " + this);
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;
}
private FarAwayClass createFarAwayObject(int i)
{
FarAwayClass fa = new FarAwayClass();
if (clientKeyGeneration) fa.setId(getId());
fa.setName("away from " + i);
fa.setDescription("so far away from " + i);
return fa;
}
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 deleteFarAways() throws Exception
{
long start = System.currentTimeMillis();
for (int i = 0; i < arr.length; i++)
{
PersistenceBroker broker = null;
try
{
broker = PersistenceBrokerFactory.createPersistenceBroker(pbKey_FarAway);
broker.beginTransaction();
broker.delete(arrFarAway[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 insertNewFarAways() 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.createPersistenceBroker(pbKey_FarAway);
broker.beginTransaction();
broker.store(arrFarAway[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);
}
protected void readFarAwaysByCursor() throws Exception
{
long start = System.currentTimeMillis();
int farAway_id = arrFarAway[0].getId();
Criteria c = new Criteria();
c.addBetween("id", new Integer(farAway_id), new Integer(farAway_id + iterationsPerThread));
Query q = new QueryByCriteria(FarAwayClass.class, c);
PersistenceBroker broker = null;
try
{
broker = PersistenceBrokerFactory.createPersistenceBroker(pbKey_FarAway);
Iterator iter = broker.getIteratorByQuery(q);
int fetchCount = 0;
while (iter.hasNext())
{
fetchCount++;
FarAwayClass a = (FarAwayClass) iter.next();
}
}
finally
{
if (broker != null) broker.close();
}
long stop = System.currentTimeMillis();
times[2] = times[2] + (stop - start);
}
}
//*******************************************************************************************************
// Helper methods
//*******************************************************************************************************
/**
* 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();
broker.clearCache();
count = broker.getCount(q);
broker.close();
}
catch (Exception e)
{
e.printStackTrace();
}
return count;
}
public int getFarAwayCount()
{
Criteria c = new Criteria();
Query q = new QueryByCriteria(FarAwayClass.class, c);
int count = 0;
try
{
PersistenceBroker broker = PersistenceBrokerFactory.createPersistenceBroker(pbKey_FarAway);
broker.clearCache();
count = broker.getCount(q);
broker.close();
}
catch (Exception e)
{
e.printStackTrace();
}
return count;
}
/**
* Setting up the test fixture.
*/
public void init() throws Exception
{
// log.info("Start init performance test");
times = new long[4];
threadCount = concurrentThreads;
if (whichTest == 1 || whichTest == 3)
{
// log.info("Init PB-API");
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 || whichTest == 3)
{
// log.info("Init ODMG-API");
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();
// log.info("End init performance test");
}
}
/**
* 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;
}
}