package org.neo4j.smack.performance;
import java.util.Date;
import org.neo4j.smack.Smack;
import org.neo4j.smack.test.util.FixedRequestClient;
import org.neo4j.smack.test.util.PerformanceRoutes;
import org.neo4j.test.ImpermanentGraphDatabase;
/**
* Meant to be used as a tool to maximize throughput in the
* entire stack, including the network layer.
*
* High scores
* smack, pipelined, 4 channels : 634 678.8525 req/second (2012-04-24, JH)
* smack, pipelined, 2 channels : 504 859.2704 req/second (2012-04-20, JH)
* smack, pipelined, single channel : 377 337.1318 req/second (2012-04-20, JH)
* jetty+jersey, pipelined, single channel : 17 470.6057 req/second (2012-04-18, JH)
* smack, non-pipelined, single channel : 8 443.8064 req/second (2012-04-18, JH)
* jetty+jersey, non-pipelined, single channel : 509.9959 req/second (2012-04-18, JH)
*
*/
public class NetworkThroughput {
private Smack server;
/**
* Gives throughput numbers over the network.
* Each value denotes transactions executed per second,
* against a server end point that does not do
* any database operations.
*/
public static final class NetworkThroughputResult {
/**
* Simple http calls are calls that wait for a
* response before the next request is sent.
*/
public double simpleHttpCalls;
/**
* Number of pipelined http calls per second.
*/
public double pipelinedCalls;
}
public static void main(String [] args) {
NetworkThroughput throughput = new NetworkThroughput();
System.out.println("Running network throughput tests.. (this may take a while)");
NetworkThroughputResult result = throughput.test();
System.out.println("Average throughput over network with simple HTTP calls: " + result.simpleHttpCalls + " requests/second");
System.out.println("Average throughput over network with pipelined HTTP calls: " + result.pipelinedCalls + " requests/second");
}
private NetworkThroughputResult test() {
NetworkThroughputResult result = new NetworkThroughputResult();
double totalSeconds = 0;
try {
//Thread.sleep(1000 * 20);
//long numRequests = 1755028000l;
long numRequests = 50000000l;
//startServer();
// Simple HTTP calls
//totalSeconds = sendXRequests("http://localhost:7473" + PerformanceRoutes.NO_SERIALIZATION_AND_NO_DESERIALIZATION, numRequests);
result.simpleHttpCalls = ((double)numRequests)/totalSeconds;
// Pipelined calls
System.out.println("Warming up..");
sendXRequestsPipelined(100000);
System.out.println("Running test..");
//totalSeconds = sendXRequestsPipelined("http://localhost:7473" + PerformanceRoutes.NO_SERIALIZATION_AND_NO_DESERIALIZATION, numRequests);
totalSeconds = sendXRequestsPipelinedMultiThreaded("http://localhost:7474/dummy/justreturn/200", numRequests, 4);
System.out.println("Did " + numRequests + " http calls in " + totalSeconds + " seconds.");
result.pipelinedCalls = ((double)numRequests)/totalSeconds;
return result;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
//stopServer();
}
}
private double sendXRequestsPipelinedMultiThreaded(String uri,
long numRequests, int numThreads) throws InterruptedException
{
Thread [] runnables = new Thread[numThreads];
final long numRequestsPerThread = numRequests / numThreads;
for(int i=0;i<numThreads;i++) {
runnables[i] = new Thread(new LoadGeneratingRunnable(i == 0, numRequestsPerThread, numThreads));
}
Date start = new Date();
for(int i=0;i<numThreads;i++) {
runnables[i].start();
}
for(int i=0;i<numThreads;i++) {
runnables[i].join();
}
Date end = new Date();
return (end.getTime() - start.getTime()) / 1000.0d;
}
private double sendXRequests(int numRequests) throws InterruptedException {
FixedRequestClient client = new FixedRequestClient("localhost", 7473, PerformanceRoutes.NO_SERIALIZATION_AND_NO_DESERIALIZATION_AND_NO_INTROSPECTION, 1);
Date start = new Date();
for(int i=0;i<numRequests;i+=1) {
client.sendBatch();
client.waitForXResponses(i);
}
Date end = new Date();
client.close();
return (end.getTime() - start.getTime()) / 1000.0d;
}
private double sendXRequestsPipelined(long numRequests) throws InterruptedException
{
int requestsPerBatch = 10;
FixedRequestClient client = new FixedRequestClient("localhost", 7473, PerformanceRoutes.NO_SERIALIZATION_AND_NO_DESERIALIZATION_AND_NO_INTROSPECTION, requestsPerBatch);
Date start = new Date();
for(int i=0;i<numRequests;i+=requestsPerBatch) {
client.sendBatch();
}
client.waitForXResponses(numRequests);
client.close();
Date end = new Date();
return (end.getTime() - start.getTime()) / 1000.0d;
}
private void startServer() {
server = new Smack("localhost", 7473, new ImpermanentGraphDatabase());
server.addRoute("",new PerformanceRoutes());
server.start();
}
private void stopServer() {
server.stop();
}
}