Not sure if that should be posted as an "answer" but the formatting is easier like that than in a comment. Thanks for providing a full test class, it was helpful to debug and experiment.
Been looking at your test implementation and indeed I was able to notice a decrease in throughput as the concurrency level increased.
I believe that what you are seeing is a side effect of your local server node not being used initially and the server caches being cold and not active enough. You need bigger warmup phases for your local node to be able to start responding fast enough and see how under higher concurrency the individual requests times do not increase.
I ran your tests (just the single session ones), when my system is under low usage and when I start your tests the results look exactly similar to yours.
However, if putting some additional tests before executing the tests with 10 - 20 - 50 requests, like so:
dseVertexQueryPerformance.testSingleSession(3000);
dseVertexQueryPerformance.testSingleSession(6000);
dseVertexQueryPerformance.testSingleSession(6000);
dseVertexQueryPerformance.testSingleSession(6000);
dseVertexQueryPerformance.testSingleSession(6000);
dseVertexQueryPerformance.testSingleSession(9000);
dseVertexQueryPerformance.testSingleSession(9000);
dseVertexQueryPerformance.testSingleSession(9000);
dseVertexQueryPerformance.testSingleSession(10);
dseVertexQueryPerformance.testSingleSession(20);
dseVertexQueryPerformance.testSingleSession(50);
dseVertexQueryPerformance.testSingleSession(100);
dseVertexQueryPerformance.testSingleSession(200);
I eventually get results like:
End Test ::SingleSession, Average Time: 2.6, Total execution time: 5.891593 ms
For 10 threads, ::SingleSession took 2.6
End Test ::SingleSession, Average Time: 4.4, Total execution time: 7.830533 ms
For 20 threads, ::SingleSession took 4.4
End Test ::SingleSession, Average Time: 1.86, Total execution time: 20.378055 ms
For 50 threads, ::SingleSession took 1.86
End Test ::SingleSession, Average Time: 1.98, Total execution time: 47.487505 ms
For 100 threads, ::SingleSession took 1.98
End Test ::SingleSession, Average Time: 2.295, Total execution time: 92.793991 ms
For 200 threads, ::SingleSession took 2.295
We can effectively see that the contention was due to the fact that DSE Graph, or the system overall, was not warm enough.
Now, looking back at those longer runs I mentioned above, I observe some more contention happening or more work when using the connected traversal source.
I would recommend instead of iterating the traversal source directly, to create a GraphStatement
out of a traversal, as explained here: https://docs.datastax.com/en/developer/java-driver-dse/1.5/manual/tinkerpop/#data-stax-drivers-execution-compatibility
So in your tests, I have changed the getAVertex(GraphTraversalSource g)
to:
public class DSEVertexQueryPerformance {
...
private GraphTraversalSource traversalSource = DseGraph.traversal();
....
public long getAVertex(DseSession dseSession) {
Instant begin = Instant.now();
dseSession.executeGraph(DseGraph.statementFromTraversal(
traversalSource.V(vertexId))
);
return Duration.between(begin, Instant.now()).toMillis();
}
By changing this method I was able to go from a ~1900 ms total execution time for, say, 9000 requests (dseVertexQueryPerformance.testSingleSession(9000);
) with your current g.V().next()
version, to a total execution time of ~1400 ms using the statementFromTraversal()
method.
Finally, I'd also recommend using asynchronous query execution methods (DseSession.executeGraphAsync()
) as it would allow you parallelize all your requests without needing thread pools on the client side, which will eventually put less pressure on the client application.