Hi,
On Fri, Jan 25, 2013 at 6:09 PM, Martin Thompson <
mjp...@gmail.com> wrote:
> Hi Simone,
>
> I assume you want the semantics of put() and take() if you talking about a
> BlockingQueue? Normal queue only have offer() and poll() which are
> non-blocking.
Yes, I need take() semantic, I can live without put() semantic.
> I have queues that are much faster than the Disruptor that do not allocate
> nodes. I'm working on a open-source project that will eventually make these
> available but that may take some time yet. On my training course we work
> through examples were the students learn to build such things.
Yeah, I read you were working on something, and that's what I was
referring to in my previous email.
I can go the way of writing it myself, but I thought to ask before
diving into it :)
> ArrayBlockingQueue does not allocate nodes internally. However you should
> note that any blocking implementation that is using j.u.c locks that it
> maintains the waiters as a linked queue internally
> (AbstractQueuedSynchronizer). So if you use locks you do not avoid garbage
> if that is your goal.
>
> What is the requirement you are trying to address? It would then be easier
> to put this in context.
It's a queue for the thread pool in Jetty.
Before you scream at me :), we have benchmarked the JDK thread pools,
and they're slower than what we have now.
We currently have a BlockingArrayQueue that uses a circular array
(that can grow) and 2 Locks to protect head and tail.
We are working on eliminating false sharing (we have a naive approach
in the current code, but it's totally broken and we know it) between
head and tail (something that does not seem to be addressed in JDK's
ConcurrentLinkedQueue).
On multicore machines, it seems that use of locks is the biggest
bottleneck, so I was looking for some lock-free implementation.
Subclassing JDK's ConcurrentLinkedQueue to maintain the queue size
kind of works, but produces garbage and ConcurrentLinkedQueue's
implementation is difficult to extend to avoid allocation (for example
to reuse Node instances).
On a related note, my experience is that queues are often mostly
empty, so array-based implementation may be subject to false sharing
on the first elements (the producer writes the array element with the
value, the consumer writes it with null).
Needless to say, spacing elements by a cache line is a massive waste
of memory :)
Any consideration/experience here ?
On a similar quest, we're trying to avoid allocation for schedulers:
java.util.Timer does not allocate but uses locks (and boy it really
sucks), while ScheduledExecutorService allocates.
Here, the problem is more difficult because the queue must be ordered.
I found a good non-blocking algorithm online (Sundell & Tsigas), but
if you have insights, they're much appreciated.