package org.apache.ojb.odmg;
import java.util.Iterator;
import junit.framework.TestCase;
import org.apache.ojb.broker.ManageableCollection;
import org.apache.ojb.broker.PBFactoryException;
import org.apache.ojb.broker.PerformanceArticle;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.PersistenceBrokerFactory;
import org.apache.ojb.broker.TestHelper;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
import org.odmg.Database;
import org.odmg.Implementation;
import org.odmg.OQLQuery;
import org.odmg.Transaction;
/**
* This TestCase contains the OJB performance benchmarks for the
* ODMG API.
* @author Matthew Baird, borrowing heavily from Thomas Mahler
*/
public class PerformanceTest extends TestCase
{
private Logger logger = LoggerFactory.getLogger("performance");
private PerformanceArticle[] arr;
private String databaseName;
/**
* the number of PerformanceArticle objects to work with.
*/
static int articleCount = 10000;
/**
* the number of iterations to perform.
*/
static int iterations = 2;
/**
* the offset value for PerformanceArticle primary keys
*/
int offsetId = 123456;
public PerformanceTest(String name)
{
super(name);
}
/**
* launches the TestCase.
* The number of Objects to work with and the number of iterations
* to be performed can be adjusted by setting them as commandline parameters.
* @param args the String[] holding the commandline parameters.
*/
public static void main(String[] args)
{
if (args.length > 0)
{
articleCount = Integer.parseInt(args[0]);
}
if (args.length > 1)
{
iterations = Integer.parseInt(args[1]);
}
String[] arr = {PerformanceTest.class.getName()};
junit.textui.TestRunner.main(arr);
}
/**
* Insert the method's description here.
* Creation date: (06.12.2000 21:58:53)
*/
public void setUp() throws PBFactoryException
{
databaseName = TestHelper.DEF_DATABASE_NAME;
arr = new PerformanceArticle[articleCount];
for (int i = 0; i < articleCount; i++)
{
PerformanceArticle a = createArticle(offsetId + i);
arr[i] = a;
}
}
/**
* Insert the method's description here.
* Creation date: (06.12.2000 21:59:14)
*/
public void tearDown()
{
databaseName = null;
}
/**
* factory method that createa an PerformanceArticle with a given id.
* @return the created PerformanceArticle object
* @param id the primary key value for the new object
*/
private PerformanceArticle createArticle(int id)
{
PerformanceArticle a = new PerformanceArticle();
a.setArticleId(id);
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;
}
/**
* deletes all PerformanceArticle created by <code>insertNewArticles</code>.
*/
protected void deleteArticles() throws Exception
{
Implementation odmg = OJB.getInstance();
Database db = odmg.newDatabase();
db.open(databaseName, Database.OPEN_READ_WRITE);
Transaction tx = odmg.newTransaction();
long start = System.currentTimeMillis();
tx.begin();
for (int i = 0; i < articleCount; i++)
{
db.deletePersistent(arr[i]);
}
tx.commit();
long stop = System.currentTimeMillis();
db.close();
logger.info("deleting " + articleCount + " Objects: " + (stop - start) + " msec");
}
/**
* create new PerformanceArticle objects and insert them into the RDBMS.
* The number of objects to create is defined by <code>articleCount</code>.
*/
protected void insertNewArticles() throws Exception
{
Implementation odmg = OJB.getInstance();
Database db = odmg.newDatabase();
db.open(databaseName, Database.OPEN_READ_WRITE);
Transaction tx = odmg.newTransaction();
long start = System.currentTimeMillis();
tx.begin();
for (int i = 0; i < articleCount; i++)
{
db.makePersistent(arr[i]);
}
tx.commit();
long stop = System.currentTimeMillis();
db.close();
logger.info("inserting " + articleCount + " Objects: " + (stop - start) + " msec");
}
/**
* read in all the PerformanceArticles from the RDBMS that have
* been inserted by <code>insertNewArticles()</code>.
* The lookup is done one by one, that is: a primary key based lookup is used.
*/
protected void readArticles() throws Exception
{
Implementation odmg = OJB.getInstance();
Database db = odmg.newDatabase();
long start = System.currentTimeMillis();
db.open(databaseName, Database.OPEN_READ_ONLY);
Transaction tx = odmg.newTransaction();
tx.begin();
for (int i = 0; i < articleCount; i++)
{
OQLQuery query = odmg.newOQLQuery();
String sql = "select allArticles from " + PerformanceArticle.class.getName() + " where articleId=" + i;
query.create(sql);
query.execute();
}
tx.commit();
long stop = System.currentTimeMillis();
db.close();
logger.info("querying " + articleCount + " Objects: " + (stop - start) + " msec");
}
/**
* read in all the PerformanceArticles from the RDBMS that have
* been inserted by <code>insertNewArticles()</code>.
* The lookup is done with a cursor fetch,
* that is: a between Statement is used to select all inserted PerformanceArticles
* and Objects are read in by fetching from the cursor (JDBC ResultSet).
*/
protected void readArticlesByCursor() throws Exception
{
// clear the cache
PersistenceBroker broker = PersistenceBrokerFactory.defaultPersistenceBroker();
broker.clearCache();
broker.close();
Implementation odmg = OJB.getInstance();
Database db = odmg.newDatabase();
db.open(databaseName, Database.OPEN_READ_WRITE);
OQLQuery query = odmg.newOQLQuery();
String sql = "select allArticles from " + PerformanceArticle.class.getName() + " where articleId between " + new Integer(offsetId) + " and " + new Integer(offsetId + articleCount);
query.create(sql);
long start = System.currentTimeMillis();
ManageableCollection collection = (ManageableCollection) query.execute();
Iterator iter = collection.ojbIterator();
int fetchCount = 0;
while (iter.hasNext())
{
fetchCount++;
PerformanceArticle a = (PerformanceArticle) iter.next();
}
long stop = System.currentTimeMillis();
db.close();
logger.info("fetching " + fetchCount + " Objects: " + (stop - start) + " msec");
}
/**
* updates all PerformanceArticles inserted by <code>insertNewArticles()</code>.
* All objects are modified and changes are written to the RDBMS with an UPDATE.
*/
protected void updateExistingArticles() throws Exception
{
Implementation odmg = OJB.getInstance();
Database db = odmg.newDatabase();
db.open(databaseName, Database.OPEN_READ_WRITE);
Transaction tx = odmg.newTransaction();
long start = System.currentTimeMillis();
tx.begin();
// update all objects
for (int i = 0; i < articleCount; i++)
{
tx.lock(arr[i], Transaction.WRITE);
arr[i].setPrice(arr[i].getPrice() * 1.95583);
}
tx.commit();
long stop = System.currentTimeMillis();
logger.info("updating " + articleCount + " Objects: " + (stop - start) + " msec");
}
/**
* this method is the driver for the complete Benchmark.
* It performs the following steps:
*
* 1.) n objects are created and inserted to the RDBMS.
* 2.) the created objects are modified. Modifications are written to the RDBMS with updates.
* 3.) All objects created in 1.) are read in by primary key based SELECT statements.
* 4.) Step 3.) is repeated to test caching facilities.
* 5.) All objects created in 1.) are read by iterating over a ResultSet.
* 6.) All objects created in 1.) are deleted with n separate DELETE Statements.
*/
public void testBenchmark()
{
try
{
logger.info("Test for ODMG-api");
for (int i = 0; i < iterations; i++)
{
logger.info("");
// store all Article objects
insertNewArticles();
// update all objects
updateExistingArticles();
// querying with empty cache
PersistenceBroker broker = PersistenceBrokerFactory.defaultPersistenceBroker();
broker.clearCache();
broker.close();
readArticles();
// querying with hot cache
readArticles();
// fetching through cursor
readArticlesByCursor();
// delete all objects
deleteArticles();
}
}
catch (Throwable t)
{
logger.error(t);
fail(t.getMessage());
}
}
}