1

The logback's asynchronous appender uses BlockingQueue. The usage scenario is multi-producer single-consumer and requires a bound queue. So both ArrayBlockingQueue and LinkedBlockingQueue should satisfy this scenario.

Here are the differences between the two queues. (From discussion of the differences between these two queues. link1 , link2)

LinkedBlockingQueue:

  1. Should have better throughput since it uses separate locks for the head and the tail.

ArrayBlockingQueue :

  1. Should have better latency since it is faster to set reference in array.
  2. Pre-allocates its backing array.

I wonder what is the determining factor in using ArrayBlockingQueue.

Here are some snippets of the LogBack source code (From AsyncAppenderBase):

produce :

// The default length of the queue is 256, which is configurable
private void put(E eventObject) {
        // If false (the default) the appender will block on appending to a full queue rather than losing the message. Set to true and the appender will just drop the message and will not block your application.
        if (neverBlock) {
            blockingQueue.offer(eventObject);
        } else {
            putUninterruptibly(eventObject);
        }
    }

consume

while (parent.isStarted()) {
      try {
           E e = parent.blockingQueue.take();
               aai.appendLoopOnAppenders(e);
           } catch (InterruptedException ie) {
               break;
           }
      }
}
zysaaa
  • 1,777
  • 2
  • 8
  • 19

1 Answers1

1

I would expect most of the contention to be in the tail/queuing lock, so the throughput/contention benefit of LinkedBlockingQueue would not be important.

The required capacity is usually pretty small (256 by default) so the preallocation is not a problem, thus ArrayBlockingQueue seems the natural fit since it doesn't have the overhead of allocating (or recycling from GC) Nodes for every enqueue operation nor the memory usage overhead.

(BTW ArrayBlockingQueue implements a circular buffer so there's no array copying/shifting).