DSE图表更多线程导致响应时间变慢

时间:2018-03-12 10:43:05

标签: java tinkerpop3 datastax-enterprise-graph

我之前问过这个问题。但再次提出一个具体的例子。

所以我在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个主题 - 6毫秒
  • 50个主题 - 34毫秒
  • 200个主题 - 146毫秒。

所以我的问题是 - 有没有办法优化它以更快地运行 - 任何需要设置的池选项等。就我而言,除了公司创建发生以外,还有更多的图形突变/查询(大约10次这样的遍历),随着线程数量的增加,总体响应时间变得不够理想。

请注意,上述响应时间也适用于简单的图形查询。因此,即使简单的读取也会变慢,因为线程会上升。 (当线程数较少时,当然非常好)。

1 个答案:

答案 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()),因为它允许您并行化所有请求,而不需要客户端的线程池,这最终会减少对客户端的压力。客户申请。