Repository: logging-log4j2 Updated Branches: refs/heads/feature/LOG4J2-1430 69f264c2e -> fdb6156a9
Add support for JCTools in AsyncAppender - thanks Anthony Maire Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/fdb6156a Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/fdb6156a Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/fdb6156a Branch: refs/heads/feature/LOG4J2-1430 Commit: fdb6156a95e36f469f070a26f4b863153a69e940 Parents: 69f264c Author: Matt Sicker <boa...@gmail.com> Authored: Sun Jun 19 17:24:41 2016 -0500 Committer: Matt Sicker <boa...@gmail.com> Committed: Sun Jun 19 17:24:41 2016 -0500 ---------------------------------------------------------------------- log4j-core/pom.xml | 8 +- .../core/async/JCToolsBlockingQueueFactory.java | 93 ++++++++++++++++++++ .../log4j/core/appender/AsyncAppenderTest.java | 5 +- ...lockingQueueFactory-JctoolsBlockingQueue.xml | 40 +++++++++ log4j-perf/pom.xml | 4 + .../perf/jmh/AsyncAppenderLog4j2Benchmark.java | 1 + .../AsyncAppenderLog4j2LocationBenchmark.java | 1 + .../perf5AsyncApndMpscQNoLoc-noOpAppender.xml | 32 +++++++ .../perf5AsyncApndMpscQWithLoc-noOpAppender.xml | 32 +++++++ pom.xml | 6 ++ src/site/xdoc/manual/appenders.xml | 8 ++ 11 files changed, 225 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fdb6156a/log4j-core/pom.xml ---------------------------------------------------------------------- diff --git a/log4j-core/pom.xml b/log4j-core/pom.xml index d2c47bf..cda09f0 100644 --- a/log4j-core/pom.xml +++ b/log4j-core/pom.xml @@ -51,12 +51,18 @@ <artifactId>disruptor</artifactId> <optional>true</optional> </dependency> - <!-- Alternative implementation of BlockingQueue for AsyncAppender --> + <!-- Alternative implementation of BlockingQueue using Conversant Disruptor for AsyncAppender --> <dependency> <groupId>com.conversantmedia</groupId> <artifactId>disruptor</artifactId> <optional>true</optional> </dependency> + <!-- Alternative implementation of BlockingQueue using JCTools for AsyncAppender --> + <dependency> + <groupId>org.jctools</groupId> + <artifactId>jctools-core</artifactId> + <optional>true</optional> + </dependency> <!-- Required for JSON support --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fdb6156a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/JCToolsBlockingQueueFactory.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/JCToolsBlockingQueueFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/JCToolsBlockingQueueFactory.java new file mode 100644 index 0000000..ccda263 --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/JCToolsBlockingQueueFactory.java @@ -0,0 +1,93 @@ +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; + +/** + * Factory for creating instances of BlockingQueues backed by JCTools {@link MpscArrayQueue}. + * + * @since 2.7 + */ +@Plugin(name = "JCToolsBlockingQueue", category = Node.CATEGORY, elementType = BlockingQueueFactory.ELEMENT_TYPE) +public class JCToolsBlockingQueueFactory<E> implements BlockingQueueFactory<E> { + + private JCToolsBlockingQueueFactory() { + } + + @Override + public BlockingQueue<E> create(final int capacity) { + return new MpscBlockingQueue<>(capacity); + } + + @PluginFactory + public static <E> JCToolsBlockingQueueFactory<E> createFactory() { + return new JCToolsBlockingQueueFactory<>(); + } + + /** + * BlockingQueue wrapper for JCTools multiple producer single consumer array queue. + */ + private static final class MpscBlockingQueue<E> extends MpscArrayQueue<E> implements BlockingQueue<E> { + + MpscBlockingQueue(final 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, final int maxElements) { + return drain(new Consumer<E>() { + @Override + public void accept(E arg0) { + c.add(arg0); + } + }, maxElements); + } + + @Override + public boolean offer(final E e, final long timeout, final TimeUnit unit) throws InterruptedException { + // TODO Auto-generated method stub + return offer(e); + } + + @Override + public E poll(final long timeout, final TimeUnit unit) throws InterruptedException { + // TODO Auto-generated method stub + return poll(); + } + + @Override + public void put(final E e) throws InterruptedException { + while (!relaxedOffer(e)) { + LockSupport.parkNanos(1L); + } + } + + @Override + public int remainingCapacity() { + return capacity() - size(); + } + + @Override + public E take() throws InterruptedException { + for (; ; ) { + final E result = poll(); + if (result != null) { + return result; + } + LockSupport.parkNanos(1L); + } + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fdb6156a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderTest.java index 076fdd0..af21d77 100644 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderTest.java +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderTest.java @@ -21,10 +21,6 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LoggingException; -import org.apache.logging.log4j.core.async.ArrayBlockingQueueFactory; -import org.apache.logging.log4j.core.async.BlockingQueueFactory; -import org.apache.logging.log4j.core.async.DisruptorBlockingQueueFactory; -import org.apache.logging.log4j.core.async.LinkedTransferQueueFactory; import org.apache.logging.log4j.junit.LoggerContextRule; import org.apache.logging.log4j.test.appender.ListAppender; import org.junit.After; @@ -50,6 +46,7 @@ public class AsyncAppenderTest { // override default blocking queue implementations "BlockingQueueFactory-ArrayBlockingQueue.xml", "BlockingQueueFactory-DisruptorBlockingQueue.xml", + "BlockingQueueFactory-JCToolsBlockingQueue.xml", "BlockingQueueFactory-LinkedTransferQueue.xml" }; } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fdb6156a/log4j-core/src/test/resources/BlockingQueueFactory-JctoolsBlockingQueue.xml ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/resources/BlockingQueueFactory-JctoolsBlockingQueue.xml b/log4j-core/src/test/resources/BlockingQueueFactory-JctoolsBlockingQueue.xml new file mode 100644 index 0000000..452faa2 --- /dev/null +++ b/log4j-core/src/test/resources/BlockingQueueFactory-JctoolsBlockingQueue.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--> +<Configuration status="OFF" name="JCToolsBlockingQueueFactory"> + + <Appenders> + <Console name="STDOUT"> + <PatternLayout pattern="%m%n"/> + </Console> + <List name="List"> + <PatternLayout pattern="%C %M %m"/> + </List> + <Async name="Async" includeLocation="true" error-ref="STDOUT"> + <AppenderRef ref="List"/> + <JCToolsBlockingQueue/> + </Async> + </Appenders> + + <Loggers> + <Root level="debug"> + <AppenderRef ref="Async"/> + </Root> + </Loggers> + +</Configuration> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fdb6156a/log4j-perf/pom.xml ---------------------------------------------------------------------- diff --git a/log4j-perf/pom.xml b/log4j-perf/pom.xml index 5240fd8..66e7d6e 100644 --- a/log4j-perf/pom.xml +++ b/log4j-perf/pom.xml @@ -94,6 +94,10 @@ <groupId>com.conversantmedia</groupId> <artifactId>disruptor</artifactId> </dependency> + <dependency> + <groupId>org.jctools</groupId> + <artifactId>jctools-core</artifactId> + </dependency> <!-- Embedded JDBC drivers for database appender tests --> <dependency> <groupId>org.hsqldb</groupId> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fdb6156a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/AsyncAppenderLog4j2Benchmark.java ---------------------------------------------------------------------- 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..e598a9c 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,6 +75,7 @@ public class AsyncAppenderLog4j2Benchmark { @Param({ "perf5AsyncApndNoLoc-noOpAppender.xml", "perf5AsyncApndDsrptrNoLoc-noOpAppender.xml", + "perf5AsyncApndMpscQNoLoc-noOpAppender.xml", "perf5AsyncApndXferQNoLoc-noOpAppender.xml" }) public String configFileName; http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fdb6156a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/AsyncAppenderLog4j2LocationBenchmark.java ---------------------------------------------------------------------- diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/AsyncAppenderLog4j2LocationBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/AsyncAppenderLog4j2LocationBenchmark.java index a5434c9..ee5124d 100644 --- a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/AsyncAppenderLog4j2LocationBenchmark.java +++ b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/AsyncAppenderLog4j2LocationBenchmark.java @@ -63,6 +63,7 @@ public class AsyncAppenderLog4j2LocationBenchmark { @Param({ "perf5AsyncApndWithLoc-noOpAppender.xml", "perf5AsyncApndDsrptrWithLoc-noOpAppender.xml", + "perf5AsyncApndMpscQWithLoc-noOpAppender.xml", "perf5AsyncApndXferQWithLoc-noOpAppender.xml" }) public String configFileName; http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fdb6156a/log4j-perf/src/main/resources/perf5AsyncApndMpscQNoLoc-noOpAppender.xml ---------------------------------------------------------------------- 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..26cd946 --- /dev/null +++ b/log4j-perf/src/main/resources/perf5AsyncApndMpscQNoLoc-noOpAppender.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache license, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the license for the specific language governing permissions and + limitations under the license. + --> +<Configuration status="OFF"> + <Appenders> + <CountingNoOp name="NoOp"> + </CountingNoOp> + <Async name="Async" blocking="true" bufferSize="262144"> + <appender-ref ref="NoOp"/> + <JCToolsBlockingQueue/> + </Async> + </Appenders> + <Loggers> + <Root level="info" includeLocation="false"> + <appender-ref ref="Async"/> + </Root> + </Loggers> +</Configuration> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fdb6156a/log4j-perf/src/main/resources/perf5AsyncApndMpscQWithLoc-noOpAppender.xml ---------------------------------------------------------------------- diff --git a/log4j-perf/src/main/resources/perf5AsyncApndMpscQWithLoc-noOpAppender.xml b/log4j-perf/src/main/resources/perf5AsyncApndMpscQWithLoc-noOpAppender.xml new file mode 100644 index 0000000..3bf3c98 --- /dev/null +++ b/log4j-perf/src/main/resources/perf5AsyncApndMpscQWithLoc-noOpAppender.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache license, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the license for the specific language governing permissions and + limitations under the license. + --> +<Configuration status="OFF"> + <Appenders> + <CountingNoOp name="NoOp"> + </CountingNoOp> + <Async name="Async" blocking="true" bufferSize="262144" includeLocation="true"> + <appender-ref ref="NoOp"/> + <JCToolsBlockingQueue/> + </Async> + </Appenders> + <Loggers> + <Root level="info"> + <appender-ref ref="Async"/> + </Root> + </Loggers> +</Configuration> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fdb6156a/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index b1cd42e..ec6bf85 100644 --- a/pom.xml +++ b/pom.xml @@ -225,6 +225,7 @@ <activemq.version>5.13.2</activemq.version> <!-- Allow Clirr severity to be overriden by the command-line option -DminSeverity=level --> <minSeverity>info</minSeverity> + <jctoolsVersion>1.2</jctoolsVersion> </properties> <pluginRepositories> <pluginRepository> @@ -616,6 +617,11 @@ <version>${conversantDisruptorVersion}</version> </dependency> <dependency> + <groupId>org.jctools</groupId> + <artifactId>jctools-core</artifactId> + <version>${jctoolsVersion}</version> + </dependency> + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fdb6156a/src/site/xdoc/manual/appenders.xml ---------------------------------------------------------------------- diff --git a/src/site/xdoc/manual/appenders.xml b/src/site/xdoc/manual/appenders.xml index e2d30ac..693bc39 100644 --- a/src/site/xdoc/manual/appenders.xml +++ b/src/site/xdoc/manual/appenders.xml @@ -213,6 +213,14 @@ </td> </tr> <tr> + <td>JCToolsBlockingQueue</td> + <td> + This uses <a href="https://jctools.github.io/JCTools/">JCTools</a>, specifically the + <abbr title="multiple producer single consumer">MPSC</abbr> bounded lock-free queue. + <!-- TODO: this need performance charts and links added --> + </td> + </tr> + <tr> <td>LinkedTransferQueue</td> <td> This uses the new in Java 7 implementation