So the interesting case is where single put, bulk take is faster than
the multi-producer. I think I know what is going on here, but I need
to do some further investigation.
For the bulk put/get case, as Jeff mentioned, if we implemented the
Disruptor using a batch stored as each element within the ring buffer
the performance is pretty good, generally over an order of magnitude
faster than the ArrayBlockingQueueEx (numbers below). However,
there's a couple of reasons why I don't like the bulk put case. In a
real system I think it is only useful for the single producer case.
In a multi-producer case it can cause head-of-line blocking issues,
where a large batch from one producer can starve the other producers
of resources. For the latency case, it is often better to allow
messages to interleave in order to get fairer distribution for
messages from all producers. Obviously with a single producer then
you don't have that problem.
The other thing with the test that I feel that 100 is an unusually
large size for a batch. For example if you are processing Ethernet
packets off the wire (and latency is important) then you'll probably
dispatching batches for each Ethernet frame. Given a maximum frame
size of 1500 bytes, then you're looking at an average message size of
15 bytes, which seems a little too small, also you'll probably have
less as there will be protocol overhead, so that that's an average
message size smaller than an Itch order delete. The original post
mentioned 25 producers running at 200 msg/sec. That would mean
potentially waiting on average 0.5 seconds to fill a batch that size
(if you wanted a Nagle's style algorithm). If you reduce the batch
size to something more realistic like 10, then the bulk put case is
only around twice as fast as the single put.
This is one of the other reasons that I removed bulk puts from version
3.0 of the Disruptor. They make benchmarks look really good, but are
probably not the best solution in real applications.
Mike.
--- Number of publishers = 1
Process 10000000 messages with Disruptor with bulk puts using
ProducerType.MULTI / BusySpin.
Test took: 0.025
Test took: 0.008
Test took: 0.008
Test took: 0.008
Process 10000000 messages with ArrayBlockingQueueEx using bulk takeAll
and bulk putAll.
Test took: 0.324
Test took: 0.268
Test took: 0.222
Test took: 0.248
--- Number of publishers = 2
Process 10000000 messages with Disruptor with bulk puts using
ProducerType.MULTI / BusySpin.
Test took: 0.016
Test took: 0.012
Test took: 0.016
Test took: 0.015
Process 10000000 messages with ArrayBlockingQueueEx using bulk takeAll
and bulk putAll.
Test took: 0.400
Test took: 0.390
Test took: 0.406
Test took: 0.353
--- Number of publishers = 4
Process 10000000 messages with Disruptor with bulk puts using
ProducerType.MULTI / BusySpin.
Test took: 0.034
Test took: 0.031
Test took: 0.031
Test took: 0.030
Process 10000000 messages with ArrayBlockingQueueEx using bulk takeAll
and bulk putAll.
Test took: 0.733
Test took: 0.710
Test took: 0.593
Test took: 0.681
--- Number of publishers = 8
Process 10000000 messages with Disruptor with bulk puts using
ProducerType.MULTI / BusySpin.
Test took: 0.067
Test took: 0.087
Test took: 0.076
Test took: 0.071
Process 10000000 messages with ArrayBlockingQueueEx using bulk takeAll
and bulk putAll.
Test took: 1.131
Test took: 1.161
Test took: 1.153
Test took: 1.143
--- Number of publishers = 16
Process 10000000 messages with Disruptor with bulk puts using
ProducerType.MULTI / BusySpin.
Test took: 0.145
Test took: 0.155
Test took: 0.176
Test took: 0.169
Process 10000000 messages with ArrayBlockingQueueEx using bulk takeAll
and bulk putAll.
Test took: 2.191
Test took: 2.176
Test took: 2.222
Test took: 2.179
> --
>
>