/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package org.fcrepo.client.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.PrintStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.fcrepo.client.FedoraClient;
import org.fcrepo.common.Constants;
import org.fcrepo.common.http.PreemptiveAuth;
import org.fcrepo.server.access.FedoraAPIAMTOM;
import org.fcrepo.server.management.FedoraAPIMMTOM;
import org.fcrepo.server.utilities.TypeUtility;
/**
* Performs test to determine the time necessary to execute
* various repository activities.
*
* @author Bill Branan
*/
public class PerformanceTests
implements Constants {
private FedoraAPIMMTOM apim;
private FedoraAPIAMTOM apia;
private static int iterations = 10;
private static int threads = 10;
private static final String pid = "demo:performance";
private static String DEMO_FOXML_TEXT;
private static String datastream =
"http://local.fedora.server/fedora-demo/simple-image-demo/coliseum-thumb.jpg";
private String host;
private String port;
private String context;
private String username;
private String password;
private String[] PIDS;
private byte[][] FOXML;
static {
// Test FOXML object
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
sb.append("<foxml:digitalObject PID=\"" + pid +
"\" VERSION=\"1.1\" xmlns:foxml=\"info:fedora/fedora-system:def/foxml#\"");
sb.append(
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"info:fedora/fedora-system:def/foxml# http://www.fedora.info/definitions/1/0/foxml1-1.xsd\">");
sb.append(" <foxml:objectProperties>");
sb.append(" <foxml:property NAME=\"info:fedora/fedora-system:def/model#state\" VALUE=\"Active\"/>");
sb.append(" <foxml:property NAME=\"info:fedora/fedora-system:def/model#label\" VALUE=\"Test Object\"/>");
sb.append(" <foxml:property NAME=\"info:fedora/fedora-system:def/model#ownerId\" VALUE=\"fedoraAdmin\"/>");
sb.append(
" <foxml:property NAME=\"info:fedora/fedora-system:def/model#createdDate\" VALUE=\"2008-07-09T19:28:04.890Z\"/>");
sb.append(
" <foxml:property NAME=\"info:fedora/fedora-system:def/view#lastModifiedDate\" VALUE=\"2008-07-09T19:32:31.750Z\"/>");
sb.append(" </foxml:objectProperties>");
sb.append(" <foxml:datastream CONTROL_GROUP=\"X\" ID=\"AUDIT\" STATE=\"A\" VERSIONABLE=\"false\">");
sb.append(" <foxml:datastreamVersion CREATED=\"2008-07-09T19:28:04.890Z\"");
sb.append(
" FORMAT_URI=\"info:fedora/fedora-system:format/xml.fedora.audit\" ID=\"AUDIT.0\" LABEL=\"Fedora Object Audit Trail\" MIMETYPE=\"text/xml\">");
sb.append(" <foxml:xmlContent>");
sb.append(" <audit:auditTrail xmlns:audit=\"info:fedora/fedora-system:def/audit#\">");
sb.append(" <audit:record ID=\"AUDREC1\">");
sb.append(" <audit:process type=\"Fedora API-M\"/>");
sb.append(" <audit:action>ingest</audit:action>");
sb.append(" <audit:componentID/>");
sb.append(" <audit:responsibility>fedoraAdmin</audit:responsibility>");
sb.append(" <audit:date>2008-07-09T19:28:04.890Z</audit:date>");
sb.append(" <audit:justification>Created New Object</audit:justification>");
sb.append(" </audit:record>");
sb.append(" </audit:auditTrail>");
sb.append(" </foxml:xmlContent>");
sb.append(" </foxml:datastreamVersion>");
sb.append(" </foxml:datastream>");
sb.append(" <foxml:datastream CONTROL_GROUP=\"X\" ID=\"DC\" STATE=\"A\" VERSIONABLE=\"true\">");
sb.append(
" <foxml:datastreamVersion CREATED=\"2008-07-09T19:28:04.890Z\" ID=\"DC1.0\" LABEL=\"Dublin Core Metadata\"");
sb.append(" MIMETYPE=\"text/xml\" SIZE=\"226\">");
sb.append(" <foxml:contentDigest DIGEST=\"none\" TYPE=\"DISABLED\"/>");
sb.append(" <foxml:xmlContent>");
sb.append(
" <oai_dc:dc xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:oai_dc=\"http://www.openarchives.org/OAI/2.0/oai_dc/\">");
sb.append(" <dc:title>Test Object</dc:title>");
sb.append(" <dc:identifier>" + pid + "</dc:identifier>");
sb.append(" </oai_dc:dc>");
sb.append(" </foxml:xmlContent>");
sb.append(" </foxml:datastreamVersion>");
sb.append(" </foxml:datastream>");
sb.append(" <foxml:datastream CONTROL_GROUP=\"X\" ID=\"XDS1\" STATE=\"A\" VERSIONABLE=\"true\">");
sb.append(
" <foxml:datastreamVersion CREATED=\"2008-07-09T19:28:58.125Z\" ID=\"XDS1.0\" LABEL=\"XML Datastream 1\" MIMETYPE=\"text/xml\" SIZE=\"41\">");
sb.append(" <foxml:contentDigest DIGEST=\"none\" TYPE=\"DISABLED\"/>");
sb.append(" <foxml:xmlContent>");
sb.append(" <xml>Datastream Content</xml>");
sb.append(" </foxml:xmlContent>");
sb.append(" </foxml:datastreamVersion>");
sb.append(" </foxml:datastream>");
sb.append(" <foxml:datastream CONTROL_GROUP=\"X\" ID=\"XDS2\" STATE=\"A\" VERSIONABLE=\"true\">");
sb.append(
" <foxml:datastreamVersion CREATED=\"2008-07-09T19:29:33.609Z\" ID=\"XDS2.0\" LABEL=\"XML Datastream 2\" MIMETYPE=\"text/xml\" SIZE=\"41\">");
sb.append(" <foxml:contentDigest DIGEST=\"none\" TYPE=\"DISABLED\"/>");
sb.append(" <foxml:xmlContent>");
sb.append(" <xml>Datastream Content</xml>");
sb.append(" </foxml:xmlContent>");
sb.append(" </foxml:datastreamVersion>");
sb.append(" </foxml:datastream>");
sb.append(" <foxml:datastream CONTROL_GROUP=\"M\" ID=\"MDS1\" STATE=\"A\" VERSIONABLE=\"true\">");
sb.append(
" <foxml:datastreamVersion CREATED=\"2008-07-09T19:31:57.593Z\" ID=\"MDS1.0\" LABEL=\"Managed Datastream 1\" MIMETYPE=\"text/xml\" SIZE=\"0\">");
sb.append(" <foxml:contentDigest DIGEST=\"none\" TYPE=\"DISABLED\"/>");
sb.append(" <foxml:binaryContent>");
sb.append(" PHhtbD5EYXRhc3RyZWFtIENvbnRlbnQ8L3htbD4=");
sb.append(" </foxml:binaryContent>");
sb.append(" </foxml:datastreamVersion>");
sb.append(" </foxml:datastream>");
sb.append(" <foxml:datastream CONTROL_GROUP=\"M\" ID=\"MDS2\" STATE=\"A\" VERSIONABLE=\"true\">");
sb.append(
" <foxml:datastreamVersion CREATED=\"2008-07-09T19:32:31.750Z\" ID=\"MDS2.0\" LABEL=\"Managed Datastream 2\" MIMETYPE=\"text/xml\" SIZE=\"0\">");
sb.append(" <foxml:contentDigest DIGEST=\"none\" TYPE=\"DISABLED\"/>");
sb.append(" <foxml:binaryContent>");
sb.append(" PHhtbD5EYXRhc3RyZWFtIENvbnRlbnQ8L3htbD4=");
sb.append(" </foxml:binaryContent>");
sb.append(" </foxml:datastreamVersion>");
sb.append(" </foxml:datastream>");
sb.append("</foxml:digitalObject>");
DEMO_FOXML_TEXT = sb.toString();
}
public void init(String host, String port, String context, String username, String password) throws Exception {
this.host = host;
this.port = port;
this.username = username;
this.password = password;
this.context = context;
String baseURL = "http://" + host + ":" + port + "/" + context;
FedoraClient fedoraClient = new FedoraClient(baseURL, username, password);
apim = fedoraClient.getAPIMMTOM();
apia = fedoraClient.getAPIAMTOM();
fedoraClient.shutdown();
PIDS = apim.getNextPID(new BigInteger(Integer.valueOf(iterations).toString()), "demo").toArray(new String[]{});
FOXML = new byte[iterations][];
for (int i = 0; i < iterations; i++) {
FOXML[i] = DEMO_FOXML_TEXT.replaceAll(pid, PIDS[i]).getBytes("UTF-8");
}
}
private void runIngest(byte[] foxml) throws Exception {
apim.ingest(TypeUtility.convertBytesToDataHandler(foxml), FOXML1_1.uri, "Ingest Test");
}
private void runAddDatastream(String pid, String dsId) throws Exception {
apim.addDatastream(pid,
dsId,
null,
"New Datastream",
true,
"text/xml",
null,
datastream,
"M",
"A",
null,
null,
"Adding Test Datastream");
}
private void runModifyDatastreamByRef(String pid) throws Exception {
apim.modifyDatastreamByReference(pid,
"MDS1",
null,
"New Label",
"text/xml",
null,
datastream,
null,
null,
"Modify Datastream Test",
false);
}
private void runModifyDatastreamByValue(String pid) throws Exception {
String dsContent = "<xml>Updated Content</xml>";
apim.modifyDatastreamByValue(pid,
"XDS1",
null,
"New Label",
"text/xml",
null,
TypeUtility.convertBytesToDataHandler(dsContent.getBytes()),
null,
null,
"Modify Datastream Test",
false);
}
private void runPurgeDatastream(String pid, String dsId) throws Exception {
apim.purgeDatastream(pid, dsId, null, null, "Purge Datastream Test", false);
}
private void runPurgeObject(String pid) throws Exception {
apim.purgeObject(pid, "Removing Test Object", false);
}
private void runGetDatastream(String pid) throws Exception {
apia.getDatastreamDissemination(pid, "MDS1", null);
}
private void runGetDatastreamRest(String pid) throws Exception {
HttpGet httpMethod = getHttpMethod(pid);
HttpClient client = getHttpClient();
HttpResponse response =
client.execute(httpMethod);
if (response.getEntity() != null) {
EntityUtils.consumeQuietly(response.getEntity());
}
httpMethod.releaseConnection();
}
/**
* @return average run time for a single operation
*/
public long runIngestTest() throws Exception {
long totalTime = 0;
long startTime = 0;
long stopTime = 0;
for (int i = 0; i < iterations; i++) {
startTime = System.currentTimeMillis();
runIngest(FOXML[0]);
stopTime = System.currentTimeMillis();
totalTime += (stopTime - startTime);
runPurgeObject(PIDS[0]);
}
long average = totalTime / iterations;
return average;
}
/**
* @return average run time for a single operation
*/
public long runAddDatastreamTest() throws Exception {
long totalTime = 0;
long startTime = 0;
long stopTime = 0;
runIngest(FOXML[0]);
for (int i = 0; i < iterations; i++) {
startTime = System.currentTimeMillis();
runAddDatastream(PIDS[0], "MDS3");
stopTime = System.currentTimeMillis();
totalTime += (stopTime - startTime);
runPurgeDatastream(PIDS[0], "MDS3");
}
runPurgeObject(PIDS[0]);
long average = totalTime / iterations;
return average;
}
/**
* @return average run time for a single operation
*/
public long runModifyDatastreamByRefTest() throws Exception {
long totalTime = 0;
long startTime = 0;
long stopTime = 0;
runIngest(FOXML[0]);
for (int i = 0; i < iterations; i++) {
startTime = System.currentTimeMillis();
runModifyDatastreamByRef(PIDS[0]);
stopTime = System.currentTimeMillis();
totalTime += (stopTime - startTime);
}
runPurgeObject(PIDS[0]);
long average = totalTime / iterations;
return average;
}
/**
* @return average run time for a single operation
*/
public long runModifyDatastreamByValueTest() throws Exception {
long totalTime = 0;
long startTime = 0;
long stopTime = 0;
runIngest(FOXML[0]);
for (int i = 0; i < iterations; i++) {
startTime = System.currentTimeMillis();
runModifyDatastreamByValue(PIDS[0]);
stopTime = System.currentTimeMillis();
totalTime += (stopTime - startTime);
}
runPurgeObject(PIDS[0]);
long average = totalTime / iterations;
return average;
}
/**
* @return average run time for a single operation
*/
public long runPurgeDatastreamTest() throws Exception {
long totalTime = 0;
long startTime = 0;
long stopTime = 0;
runIngest(FOXML[0]);
for (int i = 0; i < iterations; i++) {
runAddDatastream(PIDS[0], "MDS3");
startTime = System.currentTimeMillis();
runPurgeDatastream(PIDS[0], "MDS3");
stopTime = System.currentTimeMillis();
totalTime += (stopTime - startTime);
}
runPurgeObject(PIDS[0]);
long average = totalTime / iterations;
return average;
}
/**
* @return average run time for a single operation
*/
public long runPurgeObjectTest() throws Exception {
long totalTime = 0;
long startTime = 0;
long stopTime = 0;
for (int i = 0; i < iterations; i++) {
runIngest(FOXML[0]);
startTime = System.currentTimeMillis();
runPurgeObject(PIDS[0]);
stopTime = System.currentTimeMillis();
totalTime += (stopTime - startTime);
}
long average = totalTime / iterations;
return average;
}
/**
* @return total time to run all iterations
*/
public long runGetDatastreamTest() throws Exception {
long totalTime = 0;
long startTime = 0;
long stopTime = 0;
runIngest(FOXML[0]);
startTime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
runGetDatastream(PIDS[0]);
}
stopTime = System.currentTimeMillis();
totalTime = (stopTime - startTime);
runPurgeObject(PIDS[0]);
return totalTime;
}
/**
* @return total time to run all iterations
*/
public long runGetDatastreamRestTest() throws Exception {
long totalTime = 0;
long startTime = 0;
long stopTime = 0;
runIngest(FOXML[0]);
HttpGet httpMethod = getHttpMethod(PIDS[0]);
HttpClient client = getHttpClient();
startTime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
HttpResponse response =
client.execute(httpMethod);
EntityUtils.consumeQuietly(response.getEntity());
}
httpMethod.releaseConnection();
stopTime = System.currentTimeMillis();
totalTime = (stopTime - startTime);
runPurgeObject(PIDS[0]);
return totalTime;
}
private HttpGet getHttpMethod(String pid) {
String url = "http://" + host + ":" + port + "/" + context + "/get/" + pid + "/" + "MDS1";
HttpGet httpMethod = new HttpGet(url);
httpMethod.setHeader(HttpHeaders.CONNECTION, "Keep-Alive");
return httpMethod;
}
private HttpClient getHttpClient() {
DefaultHttpClient client = new PreemptiveAuth();
client.getCredentialsProvider().setCredentials(
new AuthScope(host, Integer.valueOf(port), "realm"),
new UsernamePasswordCredentials(username, password));
return client;
}
/**
* @return total time to run all iterations
* {ingest, addDatastream, modifyDatastreamByReference,
* modifyDatastreamByValue, purgeDatastream, purgeObject}
*/
public long[] runThroughputTests() throws Exception {
long ingestTime = 0;
long addDsTime = 0;
long modifyRefTime = 0;
long modifyValTime = 0;
long purgeDsTime = 0;
long purgeObjectTime = 0;
long startTime = 0;
long stopTime = 0;
// Ingest
startTime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
runIngest(FOXML[i]);
}
stopTime = System.currentTimeMillis();
ingestTime = (stopTime - startTime);
// Add Datastream
startTime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
runAddDatastream(PIDS[i], "MDS3");
}
stopTime = System.currentTimeMillis();
addDsTime = (stopTime - startTime);
// Modify Datastream By Reference
startTime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
runModifyDatastreamByRef(PIDS[i]);
}
stopTime = System.currentTimeMillis();
modifyRefTime = (stopTime - startTime);
// Modify Datastream By Value
startTime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
runModifyDatastreamByValue(PIDS[i]);
}
stopTime = System.currentTimeMillis();
modifyValTime = (stopTime - startTime);
// Purge Datastream
startTime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
runPurgeDatastream(PIDS[i], "MDS1");
}
stopTime = System.currentTimeMillis();
purgeDsTime = (stopTime - startTime);
// Purge Object
startTime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
runPurgeObject(PIDS[i]);
}
stopTime = System.currentTimeMillis();
purgeObjectTime = (stopTime - startTime);
// Get Datastream and Get Datastream REST results
// do not change from round-trip tests
long[] totals = {ingestTime,
addDsTime,
modifyRefTime,
modifyValTime,
purgeDsTime,
purgeObjectTime};
return totals;
}
/**
* @return total time to run all iterations with threading
* {ingest, addDatastream, modifyDatastreamByReference,
* modifyDatastreamByValue, purgeDatastream, purgeObject,
* getDatastream, getDatastreamREST}
*/
public long[] runThreadedThroughputTests() throws Exception {
long ingestTime = 0;
long addDsTime = 0;
long modifyRefTime = 0;
long modifyValTime = 0;
long purgeDsTime = 0;
long purgeObjectTime = 0;
long getDatastreamTime = 0;
long getDatastreamRestTime = 0;
long startTime = 0;
long stopTime = 0;
ExecutorService threadPool = Executors.newFixedThreadPool(threads);
// Ingest
ArrayList<Callable<Boolean>> ingestRunnerList = new ArrayList<Callable<Boolean>>();
for (int i = 0; i < iterations; i++) {
ingestRunnerList.add(new MethodRunner(MethodType.INGEST, i));
}
startTime = System.currentTimeMillis();
threadPool.invokeAll(ingestRunnerList);
stopTime = System.currentTimeMillis();
ingestTime = (stopTime - startTime);
// Add Datastream
ArrayList<Callable<Boolean>> addDatastreamRunnerList = new ArrayList<Callable<Boolean>>();
for (int i = 0; i < iterations; i++) {
addDatastreamRunnerList.add(new MethodRunner(MethodType.ADD_DATASTREAM, i));
}
startTime = System.currentTimeMillis();
threadPool.invokeAll(addDatastreamRunnerList);
stopTime = System.currentTimeMillis();
addDsTime = (stopTime - startTime);
// Modify Datastream By Reference
ArrayList<Callable<Boolean>> modDatastreamRefRunnerList = new ArrayList<Callable<Boolean>>();
for (int i = 0; i < iterations; i++) {
modDatastreamRefRunnerList.add(new MethodRunner(MethodType.MODIFY_DATASTREAM_REF, i));
}
startTime = System.currentTimeMillis();
threadPool.invokeAll(modDatastreamRefRunnerList);
stopTime = System.currentTimeMillis();
modifyRefTime = (stopTime - startTime);
// Modify Datastream By Value
ArrayList<Callable<Boolean>> modDatastreamValRunnerList = new ArrayList<Callable<Boolean>>();
for (int i = 0; i < iterations; i++) {
modDatastreamValRunnerList.add(new MethodRunner(MethodType.MODIFY_DATASTREAM_VAL, i));
}
startTime = System.currentTimeMillis();
threadPool.invokeAll(modDatastreamValRunnerList);
stopTime = System.currentTimeMillis();
modifyValTime = (stopTime - startTime);
// Purge Datastream
ArrayList<Callable<Boolean>> purgeDatastreamRunnerList = new ArrayList<Callable<Boolean>>();
for (int i = 0; i < iterations; i++) {
purgeDatastreamRunnerList.add(new MethodRunner(MethodType.PURGE_DATASTREAM, i));
}
startTime = System.currentTimeMillis();
threadPool.invokeAll(purgeDatastreamRunnerList);
stopTime = System.currentTimeMillis();
purgeDsTime = (stopTime - startTime);
// Purge Object
ArrayList<Callable<Boolean>> purgeObjectRunnerList = new ArrayList<Callable<Boolean>>();
for (int i = 0; i < iterations; i++) {
purgeObjectRunnerList.add(new MethodRunner(MethodType.PURGE_OBJECT, i));
}
startTime = System.currentTimeMillis();
threadPool.invokeAll(purgeObjectRunnerList);
stopTime = System.currentTimeMillis();
purgeObjectTime = (stopTime - startTime);
// Get Datastream
ArrayList<Callable<Boolean>> getDatastreamRunnerList = new ArrayList<Callable<Boolean>>();
for (int i = 0; i < iterations; i++) {
getDatastreamRunnerList.add(new MethodRunner(MethodType.GET_DATASTREAM, i));
}
startTime = System.currentTimeMillis();
threadPool.invokeAll(getDatastreamRunnerList);
stopTime = System.currentTimeMillis();
getDatastreamTime = (stopTime - startTime);
// Get Datastream REST
ArrayList<Callable<Boolean>> getDatastreamRestRunnerList = new ArrayList<Callable<Boolean>>();
for (int i = 0; i < iterations; i++) {
getDatastreamRestRunnerList.add(new MethodRunner(MethodType.GET_DATASTREAM_REST, i));
}
startTime = System.currentTimeMillis();
threadPool.invokeAll(getDatastreamRestRunnerList);
stopTime = System.currentTimeMillis();
getDatastreamRestTime = (stopTime - startTime);
long[] totals = {ingestTime,
addDsTime,
modifyRefTime,
modifyValTime,
purgeDsTime,
purgeObjectTime,
getDatastreamTime,
getDatastreamRestTime};
return totals;
}
private enum MethodType {
INGEST,
ADD_DATASTREAM,
MODIFY_DATASTREAM_REF,
MODIFY_DATASTREAM_VAL,
PURGE_DATASTREAM,
PURGE_OBJECT,
GET_DATASTREAM,
GET_DATASTREAM_REST;
}
/*
* Runnable class to use within threads. Executes a
* Fedora method based on the MethodType defined.
*/
private class MethodRunner implements Callable<Boolean> {
MethodType methodType;
int index;
public MethodRunner(MethodType methodType, int index) {
this.methodType = methodType;
this.index = index;
}
@Override
public Boolean call() throws Exception {
if (methodType.equals(MethodType.INGEST)) {
runIngest(FOXML[index]);
} else if (methodType.equals(MethodType.ADD_DATASTREAM)) {
runAddDatastream(PIDS[index], "MDS3");
} else if (methodType.equals(MethodType.MODIFY_DATASTREAM_REF)) {
runModifyDatastreamByRef(PIDS[index]);
} else if (methodType.equals(MethodType.MODIFY_DATASTREAM_VAL)) {
runModifyDatastreamByValue(PIDS[index]);
} else if (methodType.equals(MethodType.PURGE_DATASTREAM)) {
runPurgeDatastream(PIDS[index], "MDS1");
} else if (methodType.equals(MethodType.PURGE_OBJECT)) {
runPurgeObject(PIDS[index]);
} else if (methodType.equals(MethodType.GET_DATASTREAM)) {
runGetDatastream(PIDS[index]);
} else if (methodType.equals(MethodType.GET_DATASTREAM_REST)) {
runGetDatastreamRest(PIDS[index]);
}
return new Boolean(true);
}
}
private static double round(double d) {
int decimalPlace = 5;
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
}
private static void usage() {
System.out.println("Runs a set of performance tests over a running Fedora repository.");
System.out.println("USAGE: ant performance-tests " +
"-Dhost=HOST " +
"-Dport=PORT " +
"-Dusername=USERNAME " +
"-Dpassword=PASSWORD " +
"-Diterations=NUM-ITERATIONS " +
"-Dthreads=NUM-THREADS " +
"-Dfile=OUTPUT-FILE " +
"-Dname=TEST-NAME" +
"[-Dcontext=CONTEXT]");
System.out.println("Where:");
System.out.println(" HOST = Host on which Fedora server is running.");
System.out.println(" PORT = Port on which the Fedora server APIs can be accessed.");
System.out.println(" USERNAME = A fedora user with administrative privileges.");
System.out.println(" PASSWORD = The fedora user's password.");
System.out.println(" NUM-ITERATIONS = The number of times to perform each operation.");
System.out.println(" NUM-THREADS = The number of threads to use in the thread pool");
System.out.println(" when running threaded tests.");
System.out.println(" OUTPUT-FILE = The file to which the test results will be written.");
System.out.println(" If the file does not exist, it will be created, if the");
System.out.println(" file does exist the new results will be appended.");
System.out.println(" TEST-NAME = A name for this test run.");
System.out.println(
" CONTEXT = The application server context Fedora is deployed in. This parameter is optional");
System.out.println("Example:");
System.out.println("ant performance-tests " +
"-Dhost=localhost " +
"-Dport=8080 " +
"-Dusername=fedoraAdmin " +
"-Dpassword=fedoraAdmin " +
"-Diterations=100 " +
"-Dthreads=10 " +
"-Dfile=C:\\temp\\performance_testing_output.txt " +
"-Dname=\"Test 1\"" +
"-Dcontext=my-fedora");
System.exit(1);
}
public static void main(String[] args) throws Exception {
if (args.length < 8 || args.length > 9) {
usage();
}
String host = args[0];
String port = args[1];
String username = args[2];
String password = args[3];
String itr = args[4];
String thrds = args[5];
String output = args[6];
String name = args[7];
String context = Constants.FEDORA_DEFAULT_APP_CONTEXT;
if (args.length == 9 && !args[8].isEmpty()) {
context = args[8];
}
if (host == null || host.startsWith("$") ||
port == null || port.startsWith("$") ||
username == null || username.startsWith("$") ||
password == null || password.startsWith("$") ||
itr == null || itr.startsWith("$") ||
thrds == null || thrds.startsWith("$") ||
output == null || output.startsWith("$") ||
name == null || name.startsWith("$")) {
usage();
}
name = name.replaceAll(",", ";");
iterations = Integer.parseInt(itr);
threads = Integer.parseInt(thrds);
boolean newFile = true;
File outputFile = new File(output);
File tempFile = null;
BufferedReader reader = null;
String line = "";
if (outputFile.exists()) {
newFile = false;
// Create a copy of the file to read from
tempFile = File.createTempFile("performance-test", "tmp");
BufferedReader input = new BufferedReader(new FileReader(outputFile));
PrintStream tempOut = new PrintStream(tempFile);
while ((line = input.readLine()) != null) {
tempOut.println(line);
}
input.close();
tempOut.close();
reader = new BufferedReader(new FileReader(tempFile));
}
PrintStream out = new PrintStream(outputFile);
if (newFile) {
out.println("--------------------------------------------------------------" +
" Performance Test Results " +
"--------------------------------------------------------------");
}
PerformanceTests tests = new PerformanceTests();
tests.init(host, port, context, username, password);
System.out.println("Running Ingest Round-Trip Test...");
long ingestResults = tests.runIngestTest();
System.out.println("Running AddDatastream Round-Trip Test...");
long addDsResults = tests.runAddDatastreamTest();
System.out.println("Running ModifyDatastreamByReference Round-Trip Test...");
long modifyRefResults = tests.runModifyDatastreamByRefTest();
System.out.println("Running ModifyDatastreamByValue Round-Trip Test...");
long modifyValResults = tests.runModifyDatastreamByValueTest();
System.out.println("Running PurgeDatastream Round-Trip Test...");
long purgeDsResults = tests.runPurgeDatastreamTest();
System.out.println("Running PurgeObject Round-Trip Test...");
long purgeObjectResults = tests.runPurgeObjectTest();
System.out.println("Running GetDatastream Round-Trip Test...");
long getDatastreamResults = tests.runGetDatastreamTest();
System.out.println("Running GetDatastreamREST Round-Trip Test...");
long getDatastreamRestResults = tests.runGetDatastreamRestTest();
System.out.println("Running Throughput Tests...");
long[] tpResults = tests.runThroughputTests();
System.out.println("Running Threaded Throughput Tests...");
long[] tptResults = tests.runThreadedThroughputTests();
if (newFile) {
out.println(
"1. Test performing each operation in isolation. Time (in ms) is the average required to perform each operation.");
out.println(
"test name, ingest, addDatastream, modifyDatastreamByReference, modifyDatastreamByValue, purgeDatastream, purgeObject, getDatastream, getDatastreamREST");
} else {
line = reader.readLine();
while (line != null && line.length() > 2) {
out.println(line);
line = reader.readLine();
}
}
out.println(name + ", " +
ingestResults + ", " +
addDsResults + ", " +
modifyRefResults + ", " +
modifyValResults + ", " +
purgeDsResults + ", " +
purgeObjectResults + ", " +
getDatastreamResults / iterations + ", " +
getDatastreamRestResults / iterations);
out.println();
if (newFile) {
out.println("2. Operations-Per-Second based on results listed in item 1.");
out.println(
"test name, ingest, addDatastream, modifyDatastreamByReference, modifyDatastreamByValue, purgeDatastream, purgeObject, getDatastream, getDatastreamREST");
} else {
line = reader.readLine();
while (line != null && line.length() > 2) {
out.println(line);
line = reader.readLine();
}
}
double ingestPerSecond = 1000 / (double) ingestResults;
double addDsPerSecond = 1000 / (double) addDsResults;
double modifyRefPerSecond = 1000 / (double) modifyRefResults;
double modifyValPerSecond = 1000 / (double) modifyValResults;
double purgeDsPerSecond = 1000 / (double) purgeDsResults;
double purgeObjPerSecond = 1000 / (double) purgeObjectResults;
double getDatastreamPerSecond = 1000 / ((double) getDatastreamResults / iterations);
double getDatastreamRestPerSecond = 1000 / ((double) getDatastreamRestResults / iterations);
out.println(name + ", " +
round(ingestPerSecond) + ", " +
round(addDsPerSecond) + ", " +
round(modifyRefPerSecond) + ", " +
round(modifyValPerSecond) + ", " +
round(purgeDsPerSecond) + ", " +
round(purgeObjPerSecond) + ", " +
round(getDatastreamPerSecond) + ", " +
round(getDatastreamRestPerSecond));
out.println();
if (newFile) {
out.println(
"3. Test performing operations back-to-back. Time (in ms) is that required to perform all iterations.");
out.println(
"test name, ingest, addDatastream, modifyDatastreamByReference, modifyDatastreamByValue, purgeDatastream, purgeObject, getDatastream, getDatastreamREST");
} else {
line = reader.readLine();
while (line != null && line.length() > 2) {
out.println(line);
line = reader.readLine();
}
}
out.println(name + ", " +
tpResults[0] + ", " +
tpResults[1] + ", " +
tpResults[2] + ", " +
tpResults[3] + ", " +
tpResults[4] + ", " +
tpResults[5] + ", " +
getDatastreamResults + ", " +
getDatastreamRestResults);
out.println();
if (newFile) {
out.println("4. Operations-Per-Second based on results listed in item 3.");
out.println(
"test name, ingest, addDatastream, modifyDatastreamByReference, modifyDatastreamByValue, purgeDatastream, purgeObject, getDatastream, getDatastreamREST");
} else {
line = reader.readLine();
while (line != null && line.length() > 2) {
out.println(line);
line = reader.readLine();
}
}
double ingestItPerSecond = (double) (iterations * 1000) / tpResults[0];
double addDsItPerSecond = (double) (iterations * 1000) / tpResults[1];
double modifyRefItPerSecond = (double) (iterations * 1000) / tpResults[2];
double modifyValItPerSecond = (double) (iterations * 1000) / tpResults[3];
double purgeDsItPerSecond = (double) (iterations * 1000) / tpResults[4];
double purgeObjItPerSecond = (double) (iterations * 1000) / tpResults[5];
double getDsItPerSecond = (double) (iterations * 1000) / getDatastreamResults;
double getDsRestItPerSecond = (double) (iterations * 1000) / getDatastreamRestResults;
out.println(name + ", " +
round(ingestItPerSecond) + ", " +
round(addDsItPerSecond) + ", " +
round(modifyRefItPerSecond) + ", " +
round(modifyValItPerSecond) + ", " +
round(purgeDsItPerSecond) + ", " +
round(purgeObjItPerSecond) + ", " +
round(getDsItPerSecond) + ", " +
round(getDsRestItPerSecond));
out.println();
if (newFile) {
out.println(
"5. Test performing operations using a thread pool. Time (in ms) is that required to perform all iterations.");
out.println(
"test name, ingest, addDatastream, modifyDatastreamByReference, modifyDatastreamByValue, purgeDatastream, purgeObject, getDatastream, getDatastreamREST");
} else {
line = reader.readLine();
while (line != null && line.length() > 2) {
out.println(line);
line = reader.readLine();
}
}
out.println(name + ", " +
tptResults[0] + ", " +
tptResults[1] + ", " +
tptResults[2] + ", " +
tptResults[3] + ", " +
tptResults[4] + ", " +
tptResults[5] + ", " +
tptResults[6] + ", " +
tptResults[7]);
out.println();
if (newFile) {
out.println("6. Operations-Per-Second based on results listed in item 5.");
out.println(
"test name, ingest, addDatastream, modifyDatastreamByReference, modifyDatastreamByValue, purgeDatastream, purgeObject, getDatastream, getDatastreamREST");
} else {
line = reader.readLine();
while (line != null && line.length() > 2) {
out.println(line);
line = reader.readLine();
}
}
double thrdIngestItPerSecond = (double) (iterations * 1000) / tptResults[0];
double thrdAddDsItPerSecond = (double) (iterations * 1000) / tptResults[1];
double thrdModifyRefItPerSecond = (double) (iterations * 1000) / tptResults[2];
double thrdModifyValItPerSecond = (double) (iterations * 1000) / tptResults[3];
double thrdPurgeDsItPerSecond = (double) (iterations * 1000) / tptResults[4];
double thrdPurgeObjItPerSecond = (double) (iterations * 1000) / tptResults[5];
double thrdGetDsItPerSecond = (double) (iterations * 1000) / tptResults[6];
double thrdGetDsRestItPerSecond = (double) (iterations * 1000) / tptResults[7];
out.println(name + ", " +
round(thrdIngestItPerSecond) + ", " +
round(thrdAddDsItPerSecond) + ", " +
round(thrdModifyRefItPerSecond) + ", " +
round(thrdModifyValItPerSecond) + ", " +
round(thrdPurgeDsItPerSecond) + ", " +
round(thrdPurgeObjItPerSecond) + ", " +
round(thrdGetDsItPerSecond) + ", " +
round(thrdGetDsRestItPerSecond));
if (!newFile) {
reader.close();
tempFile.delete();
}
out.close();
System.out.println("Performance Tests Complete.");
}
}