package org.apache.ojb.broker;
import junit.framework.TestCase;
import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldDirectAccessImpl;
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.broker.util.configuration.impl.OjbConfiguration;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
import java.util.Iterator;
/**
* This TestCase contains the OJB performance benchmarks for the
* PersistenceBroker API.
* @author Thomas Mahler
*/
public class PerformanceTest extends TestCase
{
private Logger logger = LoggerFactory.getLogger("performance");
/**
* 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;
PersistenceBroker broker;
private PerformanceArticle[] arr;
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);
}
/**
* Setting up the test fixture.
*/
public void setUp()
{
try
{
// obtain broker instance
broker = PersistenceBrokerFactory.defaultPersistenceBroker();
// manipulate configuration to use maximum performance field access
OjbConfiguration conf = (OjbConfiguration) PersistenceBrokerFactory.
getConfigurator().getConfigurationFor(null);
conf.setPersistentFieldClass(PersistentFieldDirectAccessImpl.class);
}
catch (PBFactoryException e)
{
}
arr = new PerformanceArticle[articleCount];
for (int i = 0; i < articleCount; i++)
{
PerformanceArticle a = createArticle(offsetId + i);
arr[i] = a;
}
}
/**
* tearing down the test fixture.
*/
public void tearDown()
{
broker.close();
}
/**
* 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 PersistenceBrokerException
{
long start = System.currentTimeMillis();
broker.beginTransaction();
for (int i = 0; i < articleCount; i++)
{
broker.delete(arr[i]);
}
broker.commitTransaction();
long stop = System.currentTimeMillis();
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 PersistenceBrokerException
{
ObjectModificationDefaultImpl needsInsert = new ObjectModificationDefaultImpl();
needsInsert.setNeedsInsert(true);
long start = System.currentTimeMillis();
broker.beginTransaction();
for (int i = 0; i < articleCount; i++)
{
broker.store(arr[i], needsInsert);
}
broker.commitTransaction();
long stop = System.currentTimeMillis();
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 PersistenceBrokerException
{
long start = System.currentTimeMillis();
broker.beginTransaction();
for (int i = 0; i < articleCount; i++)
{
Object[] pks = {new Integer(offsetId + i)};
Identity oid = new Identity(PerformanceArticle.class, PerformanceArticle.class,pks);
PerformanceArticle a = (PerformanceArticle) broker.getObjectByIdentity(oid);
}
broker.commitTransaction();
long stop = System.currentTimeMillis();
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 PersistenceBrokerException
{
broker.clearCache();
Criteria c = new Criteria();
c.addBetween("articleId", new Integer(offsetId), new Integer(offsetId + articleCount));
Query q = new QueryByCriteria(PerformanceArticle.class, c);
long start = System.currentTimeMillis();
Iterator iter = broker.getIteratorByQuery(q);
int fetchCount = 0;
while (iter.hasNext())
{
fetchCount++;
PerformanceArticle a = (PerformanceArticle) iter.next();
}
long stop = System.currentTimeMillis();
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 PersistenceBrokerException
{
// update all objects
for (int i = 0; i < articleCount; i++)
{
arr[i].setPrice(arr[i].getPrice() * 1.95583);
}
// build mod object that tell OJB to use UPDATE
ObjectModificationDefaultImpl needsUpdate = new ObjectModificationDefaultImpl();
needsUpdate.setNeedsUpdate(true);
long start = System.currentTimeMillis();
broker.beginTransaction();
for (int i = 0; i < articleCount; i++)
{
broker.store(arr[i], needsUpdate);
}
broker.commitTransaction();
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 PB-api");
for (int i = 0; i < iterations; i++)
{
logger.info("");
// store all Article objects
insertNewArticles();
// update all objects
updateExistingArticles();
// querying with empty cache
broker.clearCache();
readArticles();
// querying with hot cache
readArticles();
// fetching through cursor
readArticlesByCursor();
// delete all objects
deleteArticles();
}
}
catch (Throwable t)
{
logger.error(t);
fail(t.getMessage());
}
}
}