You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2016/09/04 18:38:47 UTC

[31/36] logging-log4j2 git commit: Add support for JCTools in AsyncAppender - thanks Anthony Maire

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/master
Commit: fdb6156a95e36f469f070a26f4b863153a69e940
Parents: 69f264c
Author: Matt Sicker <bo...@gmail.com>
Authored: Sun Jun 19 17:24:41 2016 -0500
Committer: Matt Sicker <bo...@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