diff --git a/log4j-core/pom.xml b/log4j-core/pom.xml
index d2c47bf..48d9d1d 100644
--- a/log4j-core/pom.xml
+++ b/log4j-core/pom.xml
@@ -57,6 +57,12 @@
disruptor
true
+
+
+ org.jctools
+ jctools-core
+ 1.2
+
com.fasterxml.jackson.core
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/JctoolBlockingQueueFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/JctoolBlockingQueueFactory.java
new file mode 100644
index 0000000..964d259
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/JctoolBlockingQueueFactory.java
@@ -0,0 +1,96 @@
+package org.apache.logging.log4j.core.async;
+
+import java.util.Collection;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.LockSupport;
+
+import org.apache.logging.log4j.core.config.Node;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.jctools.queues.MpscArrayQueue;
+
+
+
+/**
+ *
+ * @since 2.7
+ */
+@Plugin(name = "JctoolBlockingQueue", category = Node.CATEGORY, elementType = BlockingQueueFactory.ELEMENT_TYPE)
+public class JctoolBlockingQueueFactory implements BlockingQueueFactory {
+
+
+ private JctoolBlockingQueueFactory() {
+ }
+
+ @Override
+ public BlockingQueue create(int capacity) {
+ return new JctoolMpscBlockingQueue<>(capacity);
+ }
+
+ @PluginFactory
+ public static JctoolBlockingQueueFactory createFactory() {
+ return new JctoolBlockingQueueFactory();
+ }
+
+
+ private static final class JctoolMpscBlockingQueue extends MpscArrayQueue implements BlockingQueue {
+
+ public JctoolMpscBlockingQueue(int capacity) {
+ super(capacity);
+ }
+
+ @Override
+ public int drainTo(final Collection super E> c) {
+ return drainTo(c, capacity());
+ }
+
+ @Override
+ public int drainTo(final Collection super E> c, int maxElements) {
+ return drain(new Consumer() {
+ @Override
+ public void accept(E arg0) {
+ c.add(arg0);
+ }
+ }, maxElements);
+ }
+
+ @Override
+ public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException {
+ // TODO Auto-generated method stub
+ return offer(e);
+ }
+
+ @Override
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ // TODO Auto-generated method stub
+ return poll();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void put(E e) throws InterruptedException {
+ while(!relaxedOffer(e)) LockSupport.parkNanos(1L);
+ }
+
+ @Override
+ public int remainingCapacity() {
+ return capacity() - size();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public E take() throws InterruptedException {
+ for(;;) {
+ E result = poll();
+ if(result != null){
+ return result;
+ }
+ LockSupport.parkNanos(1L);
+ }
+ }
+ }
+}
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/AsyncAppenderLog4j2Benchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/AsyncAppenderLog4j2Benchmark.java
index 673dce6..c39fb10 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/AsyncAppenderLog4j2Benchmark.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/AsyncAppenderLog4j2Benchmark.java
@@ -75,8 +75,9 @@
@Param({
"perf5AsyncApndNoLoc-noOpAppender.xml",
"perf5AsyncApndDsrptrNoLoc-noOpAppender.xml",
- "perf5AsyncApndXferQNoLoc-noOpAppender.xml"
+ "perf5AsyncApndMpscQNoLoc-noOpAppender.xml"
})
+ //"perf5AsyncApndXferQNoLoc-noOpAppender.xml",
public String configFileName;
@Setup(Level.Trial)
diff --git a/log4j-perf/src/main/resources/perf5AsyncApndMpscQNoLoc-noOpAppender.xml b/log4j-perf/src/main/resources/perf5AsyncApndMpscQNoLoc-noOpAppender.xml
new file mode 100644
index 0000000..70029f9
--- /dev/null
+++ b/log4j-perf/src/main/resources/perf5AsyncApndMpscQNoLoc-noOpAppender.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+