2012-12-14 42 views
2

我有一个接收来自外部源的事件的EventsManagerEvent具有typevalue并发混合队列和听众

听众可以注册到EventsManager以获知特定类型事件的成功值。

EventsManager承诺两件事情,给定类型的事件:

  • 相同的值不会连续发送两次(当听众得到通知,他们保证他们获得的价值是与以前的通知不同的值)。
  • 对于给定类型的事件,必须保留从外部源接收值的顺序。

我有一个工作​​版本,但我想提高吞吐量。

典型用途:< 1K听众,< 10K事件类型,每秒接收的(但大多数被丢弃,因为没有该类型的事件或值的注册的监听并没有改变)< 1M事件。

  • 什么是实施这种行为(例如,我可以用一个队列/每个事件类型的锁,并保持它们的ConcurrentMap但有10K队列听起来不像是个好主意),最有效的战略是什么?
  • 是否有任何现有的库可以使用可伸缩并发结构来做类似的事情?

示例:监听器lst1想要收听类型type1
的事件管理接收的事件:

event: type2, value: 2 
event: type1, value: 1 
event: type1, value: 1 //no change => discard 
event: type3, value: 4 
event: type1, value: 7 

lst1应接收,以该顺序:1(仅一次)然后7

+0

执行的事件类型有任何逻辑分组/共同性? – Woot4Moo

+0

忘了补充,目前的吞吐量和预期是什么? – Woot4Moo

+0

你可以假设不同的事件类型是独立的。说一种类型是汽车的速度,另一种是外部温度。同步版本的当前吞吐量约为每秒200k个事件。 – assylias

回答

1

我会尝试实现这个事件流

  1. 所有传入的事件被放入初始的EventQueue
  2. EventDispatcherThread读取EventQueue中,并过滤器和路线将事件转化为适当的EventQueue for each type(简单队列图)
  3. 正在阅读它的类型适当的EventQueue EventListernerThread的多个实例...

没有锁/ synchronisations需要

+0

这似乎会以最糟糕的方式进行缩放。 – Woot4Moo

+0

@ Woot4Moo另一方面,它节省了很多上下文切换。 – assylias

+0

@assylias当然我可以看到,但是我所看到的问题是,步骤3中描述的EventListenerThread可能会导致重复工作,因为这并不排除必须使用同步。或者至少有一个负载平衡的概念。 – Woot4Moo

1

此答案将随着评论的添加而改变。

IF你有外部源的控制,最快的改进是防止该源发送保证被丢弃/忽略的消息。例如,外部来源可以保留一个Map或其他允许快速查找+更新的其他数据结构。外部源将能够确定什么样的信息,将需要发送到您的EventQueue

IF控制外部电源,它应该是可能的队列将持有通用Event你有在您原来的帖子中说明。我建议添加QueueRadix Tree。我的意思是存储队列在radix tree内生成的值。这允许以下:

与平衡树不同,基数树允许在O(k)时间内查找,插入和删除O(k)时间而不是O(log n)。这似乎并不像一个 优势,因为通常ķ≥数N,但在一个平衡的树中的每个 比较字符串比较需要O(k)的最坏情况下的时间,其中许多 的是在实践中,由于速度慢长公用前缀(在 的情况下,比较从字符串的开头开始)。在一个特里,所有的 比较需要恒定的时间,但它需要m比较看看 了一个长度为m的字符串。基数树可以执行这些操作,比较次数更少,并且需要更少的节点。

UPDATE

问:

你知道一个线程安全的实现基数树的?

Concurrent Trees没有测试过这些!

API: ConcurrentRadixTree

+0

不幸的是我无法控制外部来源。所以我需要在我的末尾进行过滤。 – assylias

+0

@assylias相应地更新了我的回复。 – Woot4Moo

+0

你知道基数树的线程安全实现吗? – assylias