我之前问过这个问题。但再次提出一个具体的例子。
所以我在Mac上本地运行DSE图。我有一个最简单的顶点创建,下面是遍历。
g.addV("company").property("id", companyId)
.property("name", "company_" + companyId)
.property(VertexProperty.Cardinality.list, "domainurls", "test.com", "anothertest.com")
.next();
现在我正在使用Java TinkerPop3 API进行调用。我有这样的DseSession。
dseCluster = DseCluster.builder()
.addContactPoints(contactPoints)
.withGraphOptions(new GraphOptions().setGraphName("profilex_dev"))
.build();
dseSession = dseCluster.connect();
DseGraph.traversal(dseSession)
在多线程应用程序中重用这个GraphTraversalSource实例。我的观察,线程数越多,响应时间就越慢。
我使用Java Microbenchmarking Harness测量,下面大致是我发现的
所以我的问题是 - 有没有办法优化它以更快地运行 - 任何需要设置的池选项等。就我而言,除了公司创建发生以外,还有更多的图形突变/查询(大约10次这样的遍历),随着线程数量的增加,总体响应时间变得不够理想。
请注意,上述响应时间也适用于简单的图形查询。因此,即使简单的读取也会变慢,因为线程会上升。 (当线程数较少时,当然非常好)。
答案 0 :(得分:0)
不确定是否应将其作为"回答"但格式化比评论更容易。感谢您提供完整的测试课程,这对调试和实验很有帮助。
一直在查看您的测试实现,实际上我注意到随着并发级别的增加,吞吐量会降低。
我相信您所看到的是本地服务器节点最初未使用的副作用,并且服务器缓存很冷且不够活跃。您需要更大的预热阶段才能使本地节点能够足够快地开始响应,并了解在更高的并发性下,单个请求时间不会增加。
我运行你的测试(只有单个会话),当我的系统使用率低时,当我开始你的测试时,结果看起来与你的完全相似。
但是,如果在之前执行一些额外的测试执行10 - 20 - 50个请求,请执行以下操作:
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);
我最终得到的结果如下:
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
我们可以有效地看到争用的原因是DSE Graph或整个系统不够热。
现在,回顾上面提到的那些较长的运行,我发现在使用连接的遍历源时会发生更多争用或更多工作。
我建议不要直接迭代遍历源,而是从遍历中创建GraphStatement
,如下所述:https://docs.datastax.com/en/developer/java-driver-dse/1.5/manual/tinkerpop/#data-stax-drivers-execution-compatibility
因此,在您的测试中,我已将getAVertex(GraphTraversalSource g)
更改为:
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();
}
通过更改此方法,我可以将~1900 ms的总执行时间(例如,9000个请求(dseVertexQueryPerformance.testSingleSession(9000);
)与当前g.V().next()
版本一起执行,总执行时间为〜 1400 ms使用statementFromTraversal()
方法。
最后,我还建议使用异步查询执行方法(DseSession.executeGraphAsync()
),因为它允许您并行化所有请求,而不需要客户端的线程池,这最终会减少对客户端的压力。客户申请。