- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我的系统有两种不同类型的消息 - 类型 A 和 B。每条消息都有不同的结构 - 类型 A 包含一个 int 成员,类型 B 包含一个 double 成员。我的系统需要将这两种类型的消息传递给大量业务逻辑线程。减少延迟非常重要,因此我正在研究使用 Disruptor 以机械同情的方式将消息从主线程传递到业务逻辑线程。
我的问题是干扰器只接受环形缓冲区中的一种类型的对象。这是有道理的,因为破坏者预先分配了环形缓冲区中的对象。然而,这也使得通过 Disruptor 将两种不同类型的消息传递到我的业务逻辑线程变得困难。据我所知,我有四种选择:
将干扰器配置为使用包含固定大小字节数组 的对象(按照How should one use Disruptor (Disruptor Pattern) to build real-world message systems? 的建议)。在这种情况下,主线程必须在将消息发布到破坏者之前将消息编码为字节数组,并且每个业务逻辑线程必须在收到消息后将字节数组解码回对象。这种设置的缺点是业务逻辑线程并没有真正共享来自中断器的内存——相反,它们正在从中断器提供的字节数组中创建新对象(并因此产生垃圾)。这种设置的好处是所有业务逻辑线程都可以从同一个干扰器读取多种不同类型的消息。
将干扰器配置为使用单一类型的对象,但创建多个干扰器,每个对象类型一个。在上面的例子中,会有两个独立的干扰器——一个用于 A 类型的对象,另一个用于 B 类型的对象。这种设置的好处是主线程不必将对象编码为字节数组,而业务较少的逻辑线程可以共享与中断器中使用的对象相同的对象(不会产生垃圾)。这种设置的缺点是每个业务逻辑线程都必须以某种方式订阅来自多个干扰者的消息。
将干扰器配置为使用包含消息 A 和 B 的所有字段的单一类型的“ super ”对象。这非常违反 OO 风格,但会允许妥协在选项 #1 和 #2 之间。
将干扰器配置为使用对象引用。但是,在这种情况下,我失去了对象预分配和内存排序的性能优势。
对于这种情况,您有什么建议?我觉得选项 #2 是最干净的解决方案,但我不知道消费者是否或如何从技术上订阅来自多个干扰者的消息。如果有人可以提供有关如何实现选项 #2 的示例,将不胜感激!
最佳答案
Configure the disruptor to use objects containing a fixed size byte array (as recommended by How should one use Disruptor (Disruptor Pattern) to build real-world message systems?). In this case, the main thread must encode the messages into byte arrays before publishing them to the disruptor and each of the business logic threads must decode the byte arrays back into objects upon receipt. The downside of this setup is that the business logic threads are not truly sharing the memory from the disruptor - instead they are creating new objects (and thus creating garbage) from the byte array provided by the disruptor. The upside of this setup is that all business logic threads can read multiple different types of messages from the same disruptor.
这将是我的首选方法,但我对我们的看法略有不同用例,几乎所有我们使用过 Disruptor 的地方从某种 I/O 设备接收或发送到某种 I/O 设备,所以我们的基本货币是字节数组。您可以绕过对象创建通过使用轻量级方法进行编码。看一个例子这个,我在一个例子中使用了 Javolution 的 Struct 和 Union 类我在 Devoxx ( https://github.com/mikeb01/ticketing) 上展示过。如果你可以在onEvent返回之前完全处理对象从事件处理程序调用,那么这种方法效果很好。如果事件需要超过那个点然后你需要做一些排序数据副本,例如将其反序列化为一个对象。
Configure the disruptor to use a single type of object but create multiple disruptors, one for for each object type. In the case above, there would be two separate disruptors - one for objects of type A and another for objects of type B. The upside of this setup is that the main thread doesn't have to encode the object to a byte array and the business less logic threads can share the same objects as used in the disruptor (no garbage created). The downside of this setup is that somehow each business logic thread will have to subscribe to messages from multiple disruptors.
没有尝试过这种方法,您可能需要一个自定义的 EventProcessor可以从多个环形缓冲区轮询。
Configure the disruptor to use a single type of "super" object that contains all fields of both message A and B. This is very against OO style, but will allow for a compromise between option #1 and #2. Configure the disruptor to use object references. However, in this case I lose the performance benefits of object preallocation and memory ordering.
我们已经在一些情况下这样做了,其中一些情况下缺乏预分配是可以容忍的。它工作正常。如果你路过对象,那么你需要确保一旦你在消费者方面完成了它们。我们发现使用双“ super ”对象的调度模式使实现保持公平干净的。这样做的一个缺点是它会变得稍长GC 用一些直接的对象数组来阻止它GC 在标记阶段有更多 Activity 对象要遍历。
What do you recommend for this situation? I feel that option #2 is the cleanest solution, but I don't know whether or how consumers can technically subscribe to messages from multiple disruptors. If anyone can provide an example for how to implement option #2, it would be much appreciated!
另一种选择,如果你想要完全的灵 active data的使用,就是不使用ring buffer,而是直接talk到 Sequencer 并按照您最好的方式定义对象布局配件。
关于java - 如何使用具有多种消息类型的干扰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16845956/
我是一名优秀的程序员,十分优秀!