package net.jxta.impl.cm;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import net.jxta.id.IDFactory;
import net.jxta.peer.PeerID;
import net.jxta.peergroup.PeerGroup;
import net.jxta.peergroup.PeerGroupID;
import net.jxta.test.util.FileSystemTest;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(JMock.class)
public abstract class AbstractSrdiIndexBackendLoadTest {
private JUnit4Mockery mockContext = new JUnit4Mockery();
private File storeRoot;
private String oldSrdiImplName;
@Before
public void setUp() throws Exception {
storeRoot = FileSystemTest.createTempDirectory("SrdiIndexBackendConcurrencyTest");
oldSrdiImplName = System.getProperty(SrdiIndex.SRDI_INDEX_BACKEND_SYSPROP);
System.setProperty(SrdiIndex.SRDI_INDEX_BACKEND_SYSPROP, getSrdiIndexBackendClassname());
}
@After
public void tearDown() throws Exception {
FileSystemTest.deleteDir(storeRoot);
if(oldSrdiImplName != null) {
System.setProperty(SrdiIndex.SRDI_INDEX_BACKEND_SYSPROP, oldSrdiImplName);
} else {
System.clearProperty(SrdiIndex.SRDI_INDEX_BACKEND_SYSPROP);
}
}
protected abstract String getSrdiIndexBackendClassname();
@Test
public void testAddPerformance() throws IOException {
SrdiIndex index = new SrdiIndex(createGroup(PeerGroupID.defaultNetPeerGroupID, "group"), "testIndex");
File resultsFile = File.createTempFile("perftest_" + index.getBackendClassName(), ".csv", new File("."));
FileWriter writer = null;
try {
writer = new FileWriter(resultsFile);
add10000Records(index, writer);
measureAddRemoveTime(index, writer);
} finally {
if(writer != null) {
writer.close();
}
}
index.stop();
}
/**
* Adds 100 records for a new random peer ID, then removes that peer ID, recording the time taken per
* operation. Repeats this for 1000 peers.
*/
private void measureAddRemoveTime(SrdiIndex index, FileWriter writer) throws IOException {
List<Long> addTimes = new LinkedList<Long>();
List<Long> removeTimes = new LinkedList<Long>();
StatsTracker addTracker = new StatsTracker();
StatsTracker removeTracker = new StatsTracker();
for(int peerNum=0; peerNum < 100; peerNum++) {
PeerID pid = IDFactory.newPeerID(PeerGroupID.defaultNetPeerGroupID);
for(int opNum=0; opNum < 100; opNum++) {
long addStart = System.nanoTime();
index.add(Double.toString(Math.random()), Double.toString(Math.random()), Double.toString(Math.random()), pid, Long.MAX_VALUE);
long addEnd = System.nanoTime();
addTimes.add(addEnd - addStart);
addTracker.addResult(addEnd - addStart);
}
long removeStart = System.nanoTime();
index.remove(pid);
long removeEnd = System.nanoTime();
removeTimes.add(removeEnd - removeStart);
removeTracker.addResult(removeEnd - removeStart);
}
writer.write("add time,");
for(long addTime : addTimes) {
writer.write(Long.toString(addTime));
writer.write(',');
}
writer.write("\r\n,remove time,");
for(long removeTime : removeTimes) {
writer.write(Long.toString(removeTime));
writer.write(',');
}
writer.write("\r\n");
System.out.println("Add stats: mean=" + (addTracker.getMean() / 1000000.0) + "ms, std dev=" + (addTracker.getStdDev() / 1000000.0) + "ms");
System.out.println("Remove stats: mean=" + (removeTracker.getMean() / 1000000.0) + "ms, std dev=" + (removeTracker.getStdDev() / 1000000.0) + "ms");
}
/**
* Adds 10000 entirely random records to the index to warm it up, recording the overall
* time taken, though this is not likely to be a conclusive statistic to rely on.
*/
private void add10000Records(SrdiIndex index, FileWriter writer) throws IOException {
long phase1Start = System.nanoTime();
for(int pk=0; pk < 10; pk++) {
for(int attr=0; attr < 10; attr++) {
for(int value=0; value < 10; value++) {
for(int pid = 0; pid < 10; pid++) {
index.add(Integer.toString(pk), Integer.toString(attr), Integer.toString(value), IDFactory.newPeerID(PeerGroupID.defaultNetPeerGroupID), Long.MAX_VALUE);
}
}
}
}
long phase1End = System.nanoTime();
double timeInMs = (phase1End - phase1Start) / 1000000.0;
writer.write("setup time," + timeInMs);
writer.write("\r\n");
}
private PeerGroup createGroup(final PeerGroupID groupId, final String name) {
final PeerGroup group = mockContext.mock(PeerGroup.class, name);
mockContext.checking(new Expectations() {{
ignoring(group).getStoreHome(); will(returnValue(storeRoot.toURI()));
ignoring(group).getPeerGroupName(); will(returnValue(name));
ignoring(group).getPeerGroupID(); will(returnValue(groupId));
ignoring(group).getHomeThreadGroup(); will(returnValue(Thread.currentThread().getThreadGroup()));
}});
return group;
}
}