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 c) { + return drainTo(c, capacity()); + } + + @Override + public int drainTo(final Collection 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 @@ + + + + + + + + + + + + + + + + +