/*
*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.TreeCache;
import org.jboss.cache.lock.IsolationLevel;
import org.jboss.cache.transaction.DummyTransactionManager;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.transaction.UserTransaction;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.util.ArrayList;
import java.util.Properties;
/**
* Replicated asynchronous mode performance test for transactional TreeCache
*
* @version $Revision: 2015 $
* @author <a href="mailto:bwang@jboss.org">Ben Wang</a> May 20 2003
*/
public class ReplicatedAsyncPerfTest extends TestCase
{
TreeCache cache1_, cache2_, cache3_;
int cachingMode_ = TreeCache.REPL_ASYNC;
final String groupName_ = "TreeCacheTestGroup";
final static Properties p_;
// final static Log log_=LogFactory.getLog(ReplicatedAsyncPerfAopTest.class);
String oldFactory_ = null;
final String FACTORY = "org.jboss.cache.transaction.DummyContextFactory";
ArrayList nodeList_;
static final int depth_ = 3;
static final int children_ = 4;
DummyTransactionManager tm_;
static
{
p_ = new Properties();
p_.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.cache.transaction.DummyContextFactory");
}
public ReplicatedAsyncPerfTest(String name)
{
super(name);
}
public void setUp() throws Exception
{
super.setUp();
oldFactory_ = System.getProperty(Context.INITIAL_CONTEXT_FACTORY);
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
DummyTransactionManager.getInstance();
nodeList_ = nodeGen(depth_, children_);
tm_ = new DummyTransactionManager();
log("ReplicatedAsyncPerfAopTest: cacheMode=REPL_ASYNC");
}
public void tearDown() throws Exception
{
super.tearDown();
destroyCache(cache1_);
destroyCache(cache2_);
destroyCache(cache3_);
DummyTransactionManager.destroy();
if (oldFactory_ != null) {
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, oldFactory_);
oldFactory_ = null;
}
}
TreeCache createCache(IsolationLevel level) throws Exception
{
TreeCache cache = new TreeCache();
PropertyConfigurator config = new PropertyConfigurator();
config.configure(cache, "META-INF/replAsync-service.xml");
cache.setIsolationLevel(level);
System.out.println("cache isolation level is " + cache.getIsolationLevel());
return cache;
}
private void destroyCache(TreeCache cache) throws Exception
{
if(cache != null) {
cache.remove("/");
cache.stopService();
}
}
public void testOneCacheTx_RWLock() throws Exception
{
oneCacheTx(IsolationLevel.REPEATABLE_READ);
}
public void testOneCacheTx_SimpleLock() throws Exception
{
oneCacheTx(IsolationLevel.SERIALIZABLE);
}
protected void oneCacheTx(IsolationLevel level) throws Exception
{
log("=== 1 cache with transaction (no concurrent access) ===");
cache1_ = createCache(level);
cache1_.setTransactionManagerLookupClass("org.jboss.cache.JBossTransactionManagerLookup");
cache1_.startService();
// Formating
DecimalFormat form = new DecimalFormat("#.00");
FieldPosition fieldPos = new FieldPosition(0);
StringBuffer dumbStr = new StringBuffer();
boolean hasTx = true;
// Step 1. Add entries to the cache
long time1 = System.currentTimeMillis();
int nOps = _add(cache1_, hasTx);
long time2 = System.currentTimeMillis();
double d = (double) (time2 - time1) / nOps;
log("Time elapsed for _add is " + (time2 - time1) + " with " + nOps
+ " operations. Average per ops is: " + form.format(d, dumbStr, fieldPos) +
" msec.");
dumbStr = new StringBuffer();
// Step 2. Query the cache
time1 = System.currentTimeMillis();
nOps = _get(cache1_, hasTx);
time2 = System.currentTimeMillis();
d = (double) (time2 - time1) / nOps;
log("Time elapsed for _get is " + (time2 - time1) + " with " + nOps
+ " operations. Average per ops is: " + form.format(d, dumbStr, fieldPos) +
" msec.");
dumbStr = new StringBuffer();
// Step 3. Remove entries from the cache
time1 = System.currentTimeMillis();
nOps = _remove(cache1_, hasTx);
time2 = System.currentTimeMillis();
d = (double) (time2 - time1) / nOps;
log("Time elapsed for _remove is " + (time2 - time1) + " with " + nOps
+ " operations. Average per ops is: " + form.format(d, dumbStr, fieldPos) +
" msec.");
destroyCache(cache1_);
}
public void test2CachesTx_RWLock() throws Exception
{
twoCachesTx(IsolationLevel.REPEATABLE_READ);
}
public void test2CachesTx_SimpleLock() throws Exception
{
twoCachesTx(IsolationLevel.SERIALIZABLE);
}
protected void twoCachesTx(IsolationLevel level) throws Exception
{
log("=== 2 caches with transaction (no concurrent access) ===");
cache1_ = createCache(level);
cache2_ = createCache(level);
cache1_.setTransactionManagerLookupClass("org.jboss.cache.JBossTransactionManagerLookup");
cache2_.setTransactionManagerLookupClass("org.jboss.cache.JBossTransactionManagerLookup");
cache1_.startService();
cache2_.startService();
// Formating
DecimalFormat form = new DecimalFormat("#.00");
FieldPosition fieldPos = new FieldPosition(0);
StringBuffer dumbStr = new StringBuffer();
boolean hasTx = true;
// Step 1. Add entries to the cache
long time1 = System.currentTimeMillis();
int nOps = _add(cache1_, hasTx);
long time2 = System.currentTimeMillis();
double d = (double) (time2 - time1) / nOps;
log("Time elapsed for _add is " + (time2 - time1) + " with " + nOps
+ " operations. Average per ops is: " + form.format(d, dumbStr, fieldPos) +
" msec.");
dumbStr = new StringBuffer();
// Step 2. Query the cache
time1 = System.currentTimeMillis();
nOps = _get(cache1_, hasTx);
time2 = System.currentTimeMillis();
d = (double) (time2 - time1) / nOps;
log("Time elapsed for _get is " + (time2 - time1) + " with " + nOps
+ " operations. Average per ops is: " + form.format(d, dumbStr, fieldPos) +
" msec.");
dumbStr = new StringBuffer();
// Step 3. Remove entries from the cache
time1 = System.currentTimeMillis();
nOps = _remove(cache2_, hasTx);
time2 = System.currentTimeMillis();
d = (double) (time2 - time1) / nOps;
log("Time elapsed for _remove is " + (time2 - time1) + " with " + nOps
+ " operations. Average per ops is: " + form.format(d, dumbStr, fieldPos) +
" msec.");
destroyCache(cache1_);
destroyCache(cache2_);
}
public void test2CachesTxWithReplQueue_RWLock() throws Exception
{
twoCachesTxWithReplQueue(IsolationLevel.REPEATABLE_READ);
}
public void test2CachesTxWithReplQueue_SimpleLock() throws Exception
{
twoCachesTxWithReplQueue(IsolationLevel.SERIALIZABLE);
}
protected void twoCachesTxWithReplQueue(IsolationLevel level) throws Exception
{
log("=== 2 caches with transaction (no concurrent access) using repl queue ===");
cache1_ = createCache(level);
cache2_ = createCache(level);
cache1_.setUseReplQueue(true);
cache1_.setReplQueueInterval(5000);
cache1_.setReplQueueMaxElements(100);
cache2_.setUseReplQueue(true);
cache2_.setReplQueueInterval(5000);
cache2_.setReplQueueMaxElements(100);
cache1_.setTransactionManagerLookupClass("org.jboss.cache.JBossTransactionManagerLookup");
cache2_.setTransactionManagerLookupClass("org.jboss.cache.JBossTransactionManagerLookup");
cache1_.startService();
cache2_.startService();
// Formating
DecimalFormat form = new DecimalFormat("#.00");
FieldPosition fieldPos = new FieldPosition(0);
StringBuffer dumbStr = new StringBuffer();
boolean hasTx = true;
// Step 1. Add entries to the cache
long time1 = System.currentTimeMillis();
int nOps = _add(cache1_, hasTx);
long time2 = System.currentTimeMillis();
double d = (double) (time2 - time1) / nOps;
log("Time elapsed for _add is " + (time2 - time1) + " with " + nOps
+ " operations. Average per ops is: " + form.format(d, dumbStr, fieldPos) +
" msec.");
dumbStr = new StringBuffer();
// Step 2. Query the cache
time1 = System.currentTimeMillis();
nOps = _get(cache1_, hasTx);
time2 = System.currentTimeMillis();
d = (double) (time2 - time1) / nOps;
log("Time elapsed for _get is " + (time2 - time1) + " with " + nOps
+ " operations. Average per ops is: " + form.format(d, dumbStr, fieldPos) +
" msec.");
dumbStr = new StringBuffer();
// Step 3. Remove entries from the cache
time1 = System.currentTimeMillis();
nOps = _remove(cache2_, hasTx);
time2 = System.currentTimeMillis();
d = (double) (time2 - time1) / nOps;
log("Time elapsed for _remove is " + (time2 - time1) + " with " + nOps
+ " operations. Average per ops is: " + form.format(d, dumbStr, fieldPos) +
" msec.");
destroyCache(cache1_);
destroyCache(cache2_);
}
public void test3CachesTx_RWLock() throws Exception
{
threeCachesTx(IsolationLevel.REPEATABLE_READ);
}
public void test3CachesTx_SimpleLock() throws Exception
{
threeCachesTx(IsolationLevel.SERIALIZABLE);
}
protected void threeCachesTx(IsolationLevel level) throws Exception
{
log("=== 3 caches with transaction (no concurrent access) ===");
cache1_ = createCache(level);
cache2_ = createCache(level);
cache3_ = createCache(level);
cache1_.setTransactionManagerLookupClass("org.jboss.cache.JBossTransactionManagerLookup");
cache2_.setTransactionManagerLookupClass("org.jboss.cache.JBossTransactionManagerLookup");
cache3_.setTransactionManagerLookupClass("org.jboss.cache.JBossTransactionManagerLookup");
cache1_.startService();
cache2_.startService();
cache3_.startService();
// Formating
DecimalFormat form = new DecimalFormat("#.00");
FieldPosition fieldPos = new FieldPosition(0);
StringBuffer dumbStr = new StringBuffer();
boolean hasTx = true;
// Step 1. Add entries to the cache
long time1 = System.currentTimeMillis();
int nOps = _add(cache1_, hasTx);
long time2 = System.currentTimeMillis();
double d = (double) (time2 - time1) / nOps;
log("Time elapsed for _add is " + (time2 - time1) + " with " + nOps
+ " operations. Average per ops is: " + form.format(d, dumbStr, fieldPos) +
" msec.");
dumbStr = new StringBuffer();
// Step 2. Query the cache
time1 = System.currentTimeMillis();
nOps = _get(cache2_, hasTx);
time2 = System.currentTimeMillis();
d = (double) (time2 - time1) / nOps;
log("Time elapsed for _get is " + (time2 - time1) + " with " + nOps
+ " operations. Average per ops is: " + form.format(d, dumbStr, fieldPos) +
" msec.");
dumbStr = new StringBuffer();
// Step 3. Remove entries from the cache
time1 = System.currentTimeMillis();
nOps = _remove(cache3_, hasTx);
time2 = System.currentTimeMillis();
d = (double) (time2 - time1) / nOps;
log("Time elapsed for _remove is " + (time2 - time1) + " with " + nOps
+ " operations. Average per ops is: " + form.format(d, dumbStr, fieldPos) +
" msec.");
destroyCache(cache1_);
destroyCache(cache2_);
destroyCache(cache3_);
}
private int _add(TreeCache cache, boolean hasTx) throws Exception
{
UserTransaction tx = null;
if (hasTx) {
tx = (UserTransaction) new InitialContext(p_).lookup("UserTransaction");
}
for (int i = 0; i < nodeList_.size(); i++) {
String key = Integer.toString(i);
String value = Integer.toString(i);
if (hasTx) {
tx.begin();
cache.put((String) nodeList_.get(i), key, value);
tx.commit();
} else {
cache.put((String) nodeList_.get(i), key, value);
}
}
return nodeList_.size();
}
private int _get(TreeCache cache, boolean hasTx) throws Exception
{
UserTransaction tx = null;
if (hasTx) {
tx = (UserTransaction) new InitialContext(p_).lookup("UserTransaction");
}
for (int i = 0; i < nodeList_.size(); i++) {
String key = Integer.toString(i);
if (hasTx) {
tx.begin();
cache.get((String) nodeList_.get(i), key);
tx.commit();
} else {
cache.get((String) nodeList_.get(i), key);
}
}
return nodeList_.size();
}
private int _remove(TreeCache cache, boolean hasTx) throws Exception
{
UserTransaction tx = null;
if (hasTx) {
tx = (UserTransaction) new InitialContext(p_).lookup("UserTransaction");
}
for (int i = nodeList_.size()-1; i >= 0; i--) {
String key = Integer.toString(i);
if (hasTx) {
tx.begin();
cache.remove((String) nodeList_.get(i), key);
tx.commit();
} else {
cache.remove((String) nodeList_.get(i), key);
}
}
return nodeList_.size();
}
/**
* Generate the tree nodes quasi-exponentially. I.e., depth is the level
* of the hierarchy and children is the number of children under each node.
*/
private ArrayList nodeGen(int depth, int children)
{
ArrayList strList = new ArrayList();
ArrayList oldList = new ArrayList();
ArrayList newList = new ArrayList();
oldList.add("/");
newList.add("/");
strList.add("/");
while (depth > 0) {
// Trying to produce node name at this depth.
newList = new ArrayList();
for (int i = 0; i < oldList.size(); i++) {
for (int j = 0; j < children; j++) {
String tmp = (String) oldList.get(i);
tmp += Integer.toString(j);
if (depth != 1) tmp += "/";
newList.add(tmp);
}
}
strList.addAll(newList);
oldList = newList;
depth--;
}
log("Nodes generated: " + strList.size());
return strList;
}
public static Test suite() throws Exception
{
return new TestSuite(ReplicatedAsyncPerfTest.class);
}
private void log(String str)
{
// System.out.println(this.getClass().getName() +": " +str);
System.out.println(str);
}
}