2012-11-16 45 views
9

我有一个项目可以跟踪超过500k个对象的状态信息,程序每秒接收10k次关于这些对象的更新,更新包括新的更新或删除操作。DelayQueue更高的速度remove()?

作为该计划的内部管理的一部分,必须对这些对象进行大约每隔五分钟,为了这个目的,我把他们安置在一个DelayQueue实现Delayed接口,允许DelayQueue的拦截功能来控制的看家这些对象。

  • 新的时候,对象被放在DelayQueue上。

  • 更新后,对象是中的remove()'d,更新并重新插入到由更新信息指示的新位置。

  • 删除后,对象是的remove()'d。

我所面临的问题是,一旦该队列绕过450K对象remove()方法变成过分长时间操作。

程序是多线程的,一个线程处理更新,另一个线程处理更新。由于remove()延迟,我们得到令人讨厌的锁定性能问题,并且最终更新线程缓冲区占用了所有堆空间。

我已经设法通过创建一个DelayedWeakReference (extends WeakReference implements Delayed)来解决这个问题,它允许我在队列中保留“阴影”对象,直到它们正常过期。

这消除了性能问题,但会导致内存需求的显着增加。这样做对于实际上需要在队列中的每个对象都会产生大约5 DelayedWeakReference

有没有人知道DelayQueue附加追踪,允许快速remove()操作?或者有没有更好的方法来处理这个问题,而不消耗更多的内存?

+0

只是好奇...但是这究竟是什么(除了技术问题之外)? –

+0

它是处理防火墙状态表内容的引擎,它从防火墙获取文本输出并重构内存中的状态表。这允许您执行大量操作和分析,并且更重要的是定期导出其他格式的信息,导出NetFlow中使用的自上次更新以来的差异。 – CuddlyDragon

回答

2


我花了一些时间来思考这个,
但是读你的有趣的问题了几分钟后,这里有我的想法:
A.如果你的对象有某种类型的ID,用它来散列,实际上没有一个延迟队列,但有N个延迟队列。
这将减少锁定因子N.
将有一个中央数据结构,
持有这些N个队列。由于N已预配置,因此您可以在系统启动时创建所有N个队列。

+0

这是一个我没有考虑过的有趣的方法,将'DelayQueue'分割。使用模数将对象分配给不同的对象将会很容易,因为它们都具有唯一的ID。这可能是一种扩展的方法。 – CuddlyDragon

+0

确实,这正是我的意思。如果你能测试这一点,我将不胜感激,如果有帮助,upvote :) –

+0

这是我短期内最好的选择,并且可能会在短期到中期满足我的需求。我可能会尝试为我自己的需要设计一个更专用的队列,以提供所需的功能。 - 谢谢! – CuddlyDragon

1

如果你只需要执行管家“大约每隔五分钟”,这是配发工作来维持。

我会做的是有它运行每分钟(或更少根据需要),看它是否已自上次更新五分钟的任务。如果您使用这种方法,则不需要额外收集来维护更新,也不会更改数据结构。扫描组件的开销增加了,但是不变。执行更新的开销变得微不足道(设置字段与上次更新时间)

+0

感谢您的建议,我确实考虑定期对“HashMap”进行“全面扫描”,而不是使用“DelayQueue”。然而,我很快意识到,它需要成为该特定对象的纪念日,即它们并不都具有相同的限制。我会每五分钟对扫描的性能差异进行一些测试,而不是延迟方法。 – CuddlyDragon

0

如果我正确理解你的问题,你想对某个对象做些什么,如果它没有被触摸5分钟。

您可以有一个自定义链接列表;尾巴是最近碰过的。删除节点很快。

书籍保持线程可以每1秒醒来一次,并删除5分钟前的头部。但是,如果1秒的延迟是不可接受的,计算出准确的暂停时间

// book keeping thread 

void run() 

    synchronized(list) 

    while(true) 

     if(head==null) 
      wait(); 
     else if( head.time + 5_min > now) 
      wait(head.time + 5_min - now); 
     else 
      remove head 
      process it 


// update thread 

void add(node) 
    synchronized(list) 
    append node 
    if size==1 
     notify() 

void remove(node) 
    synchronized(list) 
    remove node  
+0

我怀疑的问题是在'DelayQueue'中搜索要删除的对象,它在内部使用'PriorityQueue',而后者又使用'Object []'来存储。我不知道LL是否会更快搜索,还是不同的是它可以在不锁定整个结构的情况下完成? – CuddlyDragon