【问题标题】:Titan performance increases when removing edges去除边缘时 Titan 性能提高
【发布时间】:2014-04-09 02:01:12
【问题描述】:

以下是我的测试程序,用于测试 Titan 中去除边缘时的性能:

顶点 v1 = g.addVertex( null ); 诠释 i = 0; long lastTime = System.currentTimeMillis(); 而(真){ 顶点 v2 = g.addVertex( null ); 可迭代迭代 = v1.getEdges(Direction.IN, "last-data" ); for( 边 e : 可迭代 ) { e.删除(); } v2.addEdge(“最后一个数据”,v1); g.commit(); 如果 ( 我 % 100 == 0 ) { 持续时间长 = ( System.currentTimeMillis() - lastTime ); System.out.println("count:" + String.format("%7s", i) + ", duration:" + String.format("%7s", duration) + "ms"); lastTime = System.currentTimeMillis(); } // 万一 我++; } // 结束而

随着时间的推移,移除边缘所需的时间会越来越长,即使边缘的数量始终保持为 1。

这是一个错误吗? 由于边缘的数量始终为 1,因此移除边缘所需的时间不应该保持不变吗? 是什么导致了这种行为? 无论如何解决方法?

【问题讨论】:

  • 您使用的是哪个后端?卡桑德拉?
  • 是的,我使用 cassandra 2.0.4 作为后端存储。是 cassandra 导致了这个问题吗?

标签: performance titan


【解决方案1】:

可以在每个创建的v2 上执行setProperty 加速降级,如下所示:

    byte[] bytes = new byte[ 65536 ];
    Arrays.fill( bytes, (byte) 0 );

    Vertex v1 = g.addVertex( null );
    Edge pE = null;

    int i = 0;
    long lastTime = System.currentTimeMillis();
    while ( true ) {
        Vertex v2 = g.addVertex( null );
        v2.setProperty( "chunk", bytes );

        if ( pE != null ) {
            pE.remove();
        }

        pE = v2.addEdge( "last-data", v1 );

        g.commit();

        if ( i % 1000 == 0 ) {
            long duration = ( System.currentTimeMillis() - lastTime );
            System.out.println( "count:" + String.format( "%7s", i ) + ", duration:" + String.format( "%7s", duration ) + "ms" );
            lastTime = System.currentTimeMillis();
        } // end if
        i++;
    } // end while

即使我保持之前的优势pE,性能仍会攀升,但速度会较慢(少于 50000 次循环)。

【讨论】:

  • 嘿,梅尔文,请分享您的测试输出,以便每个人都知道我们在谈论哪些数字。这是我的 5000 个循环:dpaste.com/1776449
  • 嗨丹尼尔和斯蒂芬。我已经尝试过使用 berkeleyje、嵌入式 cassandra 和远程 cassandra 的 Titan。结果是here,连同我的测试程序。嵌入式和远程 cassandra 的性能似乎都在攀升,但对于 berkeleyje 而言并非如此。
【解决方案2】:

当您删除一条边时,它可能会从图的角度消失,但实际上它已被删除,以便在未来的压缩中删除。

您的代码正在向一个现有顶点添加边,即v1,(以及每个循环上新创建的顶点)并通过从v1 中删除边来删除它。这意味着随着被删除边的数量在压缩之前增加,您必须读取墓碑数据以到达最后添加的边。

除了执行压缩之外,另一种方法是从相反方向(即从v2)删除边缘或通过其 ID 删除边缘。这些方法让我克服了这些问题。具体给定您的代码,假设这是一个现实世界的问题,您正在从超级节点快速添加/删除边,那么某种形式的以顶点为中心的查询可能会有所帮助......比如:

v1.query().limit(1).edges()

可能修复您的“测试代码”,但您必须尝试看看。这种方法对我有用(您可以粘贴到 Titan Gremlin REPL):

g = TitanFactory.open('conf/titan-cassandra.properties')

v1 = g.addVertex(null)

bytes = new byte[ 65536 ]
Arrays.fill( bytes, (byte) 0 )

i = 0;
lastTime = System.currentTimeMillis();
toRemove = null
while ( true ) {
  def v2 = g.addVertex( null );
  v2.setProperty('b',bytes)

  if (toRemove != null) toRemove.remove()

  toRemove = v2.addEdge( "last-data", v1 );

  g.commit();

  if ( i % 100 == 0 ) {
      def duration = ( System.currentTimeMillis() - lastTime );
      println "count:" + String.format( "%7s", i ) + ", duration:" + String.format( "%7s", duration ) + "ms"
      lastTime = System.currentTimeMillis();
  } // end if
  i++;
} 

【讨论】:

  • 有趣....我不小心让您的程序意外运行。达到大约 3M 边缘,没有太多退化。有点奇怪。无论如何,我的回答仍然有效,因为我以前看到过这种行为。
  • 3M 边?你的意思是3M循环?因为我在每个循环中都删除了边缘,所以在任何时候都应该有 1 个边缘(正如你从图表的角度所说的那样)。我在 i7 桌面上运行,我几乎立即看到降级效果(少于 10000 个循环)
  • 我试过v1.query().limit(1).edges();,没有帮助。 v1.getEdges( Direction.IN, "last-data" ); 不是和v1.query().direction( Direction.IN ).labels( "last-data" ).edges(); 一样,是一个顶点查询吗?
  • 我的意思是 3M 循环,但我的配置有误,所以我之前的回答很糟糕。在@daniel-kuppitz 的帮助下,我能够重现您的问题。正如你提到的,我开始看到大约 10000 个循环的性能下降。我已经更新了我的答案,并包含了一个最终为我工作的 groovy 脚本。即使使用该模型,我也看到了峰值,但我认为这只是由于 cassandra 必须刷新提交日志。如果您不在循环的每个周期都提交,您可能会做得更好。
  • 我已经发布了我的结果here。我认为我的测试程序与here@the titan wiki 描述的程序非常相似,但我无法达到稳定的性能,尽管它总是在每个循环中做同样的事情。
【解决方案3】:

性能下降很可能是由于堆积了标记先前添加的边缘删除的墓碑。这些仅在下一次压实时被清除。这就是为什么您会看到 Cassandra 的性能受到影响,而 BerkeleyJe 的性能受到影响(它以不同的方式处理删除)。

有一些调整选项可以为此类用例获得更好的性能,但从根本上说,这种行为不会消失。 我们正在努力支持边缘上的生存时间标记,这将允许您为边缘指定过期时间,如果适用的话,这将是一种在这种情况下处理删除的更具可扩展性的方式。

【讨论】:

  • 如果是这种情况,那么在压缩之后,性能应该不会恢复正常,但是到目前为止我观察到性能一直在下降。无论如何,谢谢。
  • 好的,我从斯蒂芬那里了解到压缩是一种管理功能。我以为它是一个周期性的运行时函数。
猜你喜欢
  • 1970-01-01
  • 2023-03-05
  • 2019-04-05
  • 2012-07-09
  • 2011-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-03
相关资源
最近更新 更多