You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2022/04/26 08:08:41 UTC

[logging-log4j2] branch release-2.x updated (6edf507ce8 -> 97b8c1dc4f)

This is an automated email from the ASF dual-hosted git repository.

rpopma pushed a change to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


    from 6edf507ce8 Fix flaky ServiceLoaderUtilTest
     new 06b75ef230 LOG4J2-3473 add garbage-free version of TimeoutBlockingWaitStrategy and make this the default Async Loggers WaitStrategy
     new d7d60c6ed7 LOG4J2-3473 update for changes made with LOG4J2-3472
     new 97b8c1dc4f LOG4J2-3473 DOC update manual for garbage-free logging

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 NOTICE.txt                                         |   3 +
 .../async/DefaultAsyncWaitStrategyFactory.java     |   1 -
 .../logging/log4j/core/async/DisruptorUtil.java    |  13 +-
 .../core/async/TimeoutBlockingWaitStrategy.java    | 135 +++++++++++++++++++++
 .../async/AsyncWaitStrategyFactoryConfigTest.java  |   1 -
 ...egyFactoryIncorrectConfigGlobalLoggersTest.java |   1 -
 src/site/xdoc/manual/garbagefree.xml               |   5 +-
 7 files changed, 145 insertions(+), 14 deletions(-)
 create mode 100644 log4j-core/src/main/java/org/apache/logging/log4j/core/async/TimeoutBlockingWaitStrategy.java


Re: [logging-log4j2] 03/03: LOG4J2-3473 DOC update manual for garbage-free logging

Posted by Remko Popma <re...@gmail.com>.
Yes, thank you for pointing that out!
Fixed now.
:-)

On Wed, Apr 27, 2022 at 12:43 AM Matt Sicker <bo...@gmail.com> wrote:

> I think the next version is 2.18.0 at this point.
>
> On Tue, Apr 26, 2022 at 3:08 AM <rp...@apache.org> wrote:
> >
> > This is an automated email from the ASF dual-hosted git repository.
> >
> > rpopma pushed a commit to branch release-2.x
> > in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
> >
> > commit 97b8c1dc4f320e855f26a0690651fc062f08361a
> > Author: Remko Popma <re...@yahoo.com>
> > AuthorDate: Fri Apr 22 05:15:15 2022 +0900
> >
> >     LOG4J2-3473 DOC update manual for garbage-free logging
> > ---
> >  src/site/xdoc/manual/garbagefree.xml | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/src/site/xdoc/manual/garbagefree.xml
> b/src/site/xdoc/manual/garbagefree.xml
> > index b1c50aef39..6f68a37673 100644
> > --- a/src/site/xdoc/manual/garbagefree.xml
> > +++ b/src/site/xdoc/manual/garbagefree.xml
> > @@ -111,9 +111,12 @@
> >              will result in temporary objects being created during
> steady-state logging.
> >              </p>
> >              <p>
> > -              <b>Note 2:</b> the Async Logger Timeout wait strategy
> (the default) and the Block wait strategy
> > +              <b>Note 2:</b> as of version 2.17.3, the default Async
> Logger wait strategy used by Log4j
> > +              (Timeout) is garbage-free. Some of the wait strategies
> included in LMAX disruptor 3.4.4,
> > +              especially <tt>TimeoutBlockingWaitStrategy</tt> and
> <tt>BlockingWaitStrategy</tt> (Block)
> >                are not garbage-free since they
> >                cause
> <tt>java.util.concurrent.locks.AbstractQueuedSynchronizer$Node</tt> objects
> to be created.
> > +              The default wait strategy used by Log4j uses a
> synchronized block instead of a ReentrantLock to avoid this problem.
> >                The Yield and Sleep wait strategies are garbage-free.
> (For configuring predefined wait strategies, see
> >                <a href="async.html#SysPropsAllAsync">here</a> and
> >                <a href="async.html#SysPropsMixedSync-Async">here</a>,
> >
>

Re: [logging-log4j2] 03/03: LOG4J2-3473 DOC update manual for garbage-free logging

Posted by Matt Sicker <bo...@gmail.com>.
I think the next version is 2.18.0 at this point.

On Tue, Apr 26, 2022 at 3:08 AM <rp...@apache.org> wrote:
>
> This is an automated email from the ASF dual-hosted git repository.
>
> rpopma pushed a commit to branch release-2.x
> in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
>
> commit 97b8c1dc4f320e855f26a0690651fc062f08361a
> Author: Remko Popma <re...@yahoo.com>
> AuthorDate: Fri Apr 22 05:15:15 2022 +0900
>
>     LOG4J2-3473 DOC update manual for garbage-free logging
> ---
>  src/site/xdoc/manual/garbagefree.xml | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/src/site/xdoc/manual/garbagefree.xml b/src/site/xdoc/manual/garbagefree.xml
> index b1c50aef39..6f68a37673 100644
> --- a/src/site/xdoc/manual/garbagefree.xml
> +++ b/src/site/xdoc/manual/garbagefree.xml
> @@ -111,9 +111,12 @@
>              will result in temporary objects being created during steady-state logging.
>              </p>
>              <p>
> -              <b>Note 2:</b> the Async Logger Timeout wait strategy (the default) and the Block wait strategy
> +              <b>Note 2:</b> as of version 2.17.3, the default Async Logger wait strategy used by Log4j
> +              (Timeout) is garbage-free. Some of the wait strategies included in LMAX disruptor 3.4.4,
> +              especially <tt>TimeoutBlockingWaitStrategy</tt> and <tt>BlockingWaitStrategy</tt> (Block)
>                are not garbage-free since they
>                cause <tt>java.util.concurrent.locks.AbstractQueuedSynchronizer$Node</tt> objects to be created.
> +              The default wait strategy used by Log4j uses a synchronized block instead of a ReentrantLock to avoid this problem.
>                The Yield and Sleep wait strategies are garbage-free. (For configuring predefined wait strategies, see
>                <a href="async.html#SysPropsAllAsync">here</a> and
>                <a href="async.html#SysPropsMixedSync-Async">here</a>,
>

[logging-log4j2] 03/03: LOG4J2-3473 DOC update manual for garbage-free logging

Posted by rp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rpopma pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 97b8c1dc4f320e855f26a0690651fc062f08361a
Author: Remko Popma <re...@yahoo.com>
AuthorDate: Fri Apr 22 05:15:15 2022 +0900

    LOG4J2-3473 DOC update manual for garbage-free logging
---
 src/site/xdoc/manual/garbagefree.xml | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/site/xdoc/manual/garbagefree.xml b/src/site/xdoc/manual/garbagefree.xml
index b1c50aef39..6f68a37673 100644
--- a/src/site/xdoc/manual/garbagefree.xml
+++ b/src/site/xdoc/manual/garbagefree.xml
@@ -111,9 +111,12 @@
             will result in temporary objects being created during steady-state logging.
             </p>
             <p>
-              <b>Note 2:</b> the Async Logger Timeout wait strategy (the default) and the Block wait strategy
+              <b>Note 2:</b> as of version 2.17.3, the default Async Logger wait strategy used by Log4j
+              (Timeout) is garbage-free. Some of the wait strategies included in LMAX disruptor 3.4.4,
+              especially <tt>TimeoutBlockingWaitStrategy</tt> and <tt>BlockingWaitStrategy</tt> (Block)
               are not garbage-free since they
               cause <tt>java.util.concurrent.locks.AbstractQueuedSynchronizer$Node</tt> objects to be created.
+              The default wait strategy used by Log4j uses a synchronized block instead of a ReentrantLock to avoid this problem.
               The Yield and Sleep wait strategies are garbage-free. (For configuring predefined wait strategies, see
               <a href="async.html#SysPropsAllAsync">here</a> and
               <a href="async.html#SysPropsMixedSync-Async">here</a>,


[logging-log4j2] 01/03: LOG4J2-3473 add garbage-free version of TimeoutBlockingWaitStrategy and make this the default Async Loggers WaitStrategy

Posted by rp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rpopma pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 06b75ef230dae1b037c0cf26dfcbb53322982517
Author: Remko Popma <re...@yahoo.com>
AuthorDate: Fri Apr 15 12:23:50 2022 +0900

    LOG4J2-3473 add garbage-free version of TimeoutBlockingWaitStrategy and make this the default Async Loggers WaitStrategy
---
 NOTICE.txt                                         |   3 +
 .../logging/log4j/core/async/DisruptorUtil.java    |   1 -
 .../core/async/TimeoutBlockingWaitStrategy.java    | 135 +++++++++++++++++++++
 3 files changed, 138 insertions(+), 1 deletion(-)

diff --git a/NOTICE.txt b/NOTICE.txt
index a18190b0c7..243a0391fb 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -15,3 +15,6 @@ Copyright 2002-2012 Ramnivas Laddad, Juergen Hoeller, Chris Beams
 
 picocli (http://picocli.info)
 Copyright 2017 Remko Popma
+
+TimeoutBlockingWaitStrategy.java and parts of Util.java
+Copyright 2011 LMAX Ltd.
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java
index 5e292398a8..4924202de0 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java
@@ -25,7 +25,6 @@ import com.lmax.disruptor.BlockingWaitStrategy;
 import com.lmax.disruptor.BusySpinWaitStrategy;
 import com.lmax.disruptor.ExceptionHandler;
 import com.lmax.disruptor.SleepingWaitStrategy;
-import com.lmax.disruptor.TimeoutBlockingWaitStrategy;
 import com.lmax.disruptor.WaitStrategy;
 import com.lmax.disruptor.YieldingWaitStrategy;
 import org.apache.logging.log4j.Logger;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/TimeoutBlockingWaitStrategy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/TimeoutBlockingWaitStrategy.java
new file mode 100644
index 0000000000..804e9c901d
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/TimeoutBlockingWaitStrategy.java
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+// Where the above is the copyright notice of the derivate work,
+// below is the copyright notice of the original source of this work:
+/*
+ * Copyright 2011 LMAX Ltd.
+ *
+ * Licensed 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.
+ */
+package org.apache.logging.log4j.core.async;
+
+import com.lmax.disruptor.AlertException;
+import com.lmax.disruptor.Sequence;
+import com.lmax.disruptor.SequenceBarrier;
+import com.lmax.disruptor.TimeoutException;
+import com.lmax.disruptor.WaitStrategy;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Blocking strategy that uses a lock and condition variable for {@link EventProcessor}s waiting on a barrier.
+ * However, it will periodically wake up if it has been idle for specified period by throwing a
+ * {@link TimeoutException}.  To make use of this, the event handler class should override
+ * {@link EventHandler#onTimeout(long)}, which the {@link BatchEventProcessor} will call if the timeout occurs.
+ *
+ * <p>This strategy can be used when throughput and low-latency are not as important as CPU resource.
+ */
+// IMPLEMENTATION NOTE:
+// This is a copy of the com.lmax.disruptor.TimeoutBlockingWaitStrategy class in disruptor-4.0.0-RC1.
+// The difference between this code and the implementation of this class in disruptor-3.4.4
+// is that this class is garbage-free, because it uses a synchronized block instead of a ReentrantLock.
+// This class is package-protected, so that it can be used internally as the default WaitStrategy
+// by Log4j Async Loggers, but can be removed in a future Log4j release without impacting binary compatibility.
+// (disruptor-4.0.0-RC1 requires Java 11 and has other incompatible changes so cannot be used in Log4j 2.x.)
+class TimeoutBlockingWaitStrategy implements WaitStrategy {
+    private final Object mutex = new Object();
+    private final long timeoutInNanos;
+
+    /**
+     * @param timeout how long to wait before waking up
+     * @param units   the unit in which timeout is specified
+     */
+    public TimeoutBlockingWaitStrategy(final long timeout, final TimeUnit units) {
+        timeoutInNanos = units.toNanos(timeout);
+    }
+
+    @Override
+    public long waitFor(
+            final long sequence,
+            final Sequence cursorSequence,
+            final Sequence dependentSequence,
+            final SequenceBarrier barrier)
+            throws AlertException, InterruptedException, TimeoutException {
+        long timeoutNanos = timeoutInNanos;
+
+        long availableSequence;
+        if (cursorSequence.get() < sequence) {
+            synchronized (mutex) {
+                while (cursorSequence.get() < sequence) {
+                    barrier.checkAlert();
+                    timeoutNanos = awaitNanos(mutex, timeoutNanos);
+                    if (timeoutNanos <= 0) {
+                        throw TimeoutException.INSTANCE;
+                    }
+                }
+            }
+        }
+
+        while ((availableSequence = dependentSequence.get()) < sequence) {
+            barrier.checkAlert();
+        }
+
+        return availableSequence;
+    }
+
+    @Override
+    public void signalAllWhenBlocking() {
+        synchronized (mutex) {
+            mutex.notifyAll();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "TimeoutBlockingWaitStrategy{" +
+                "mutex=" + mutex +
+                ", timeoutInNanos=" + timeoutInNanos +
+                '}';
+    }
+
+    // below code is from com.lmax.disruptor.util.Util class in disruptor 4.0.0-RC1
+    private static final int ONE_MILLISECOND_IN_NANOSECONDS = 1_000_000;
+
+    /**
+     * @param mutex        The object to wait on
+     * @param timeoutNanos The number of nanoseconds to wait for
+     * @return the number of nanoseconds waited (approximately)
+     * @throws InterruptedException if the underlying call to wait is interrupted
+     */
+    private static long awaitNanos(final Object mutex, final long timeoutNanos) throws InterruptedException {
+        long millis = timeoutNanos / ONE_MILLISECOND_IN_NANOSECONDS;
+        long nanos = timeoutNanos % ONE_MILLISECOND_IN_NANOSECONDS;
+
+        long t0 = System.nanoTime();
+        mutex.wait(millis, (int) nanos);
+        long t1 = System.nanoTime();
+
+        return timeoutNanos - (t1 - t0);
+    }
+}


[logging-log4j2] 02/03: LOG4J2-3473 update for changes made with LOG4J2-3472

Posted by rp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rpopma pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit d7d60c6ed73fd0facf3e6afa598edff351c74a22
Author: Remko Popma <re...@yahoo.com>
AuthorDate: Thu Apr 21 20:19:34 2022 +0900

    LOG4J2-3473 update for changes made with LOG4J2-3472
---
 .../log4j/core/async/DefaultAsyncWaitStrategyFactory.java    |  1 -
 .../org/apache/logging/log4j/core/async/DisruptorUtil.java   | 12 +++---------
 .../log4j/core/async/AsyncWaitStrategyFactoryConfigTest.java |  1 -
 ...cWaitStrategyFactoryIncorrectConfigGlobalLoggersTest.java |  1 -
 4 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DefaultAsyncWaitStrategyFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DefaultAsyncWaitStrategyFactory.java
index bbe3af696a..a5c54ae4ed 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DefaultAsyncWaitStrategyFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DefaultAsyncWaitStrategyFactory.java
@@ -19,7 +19,6 @@ package org.apache.logging.log4j.core.async;
 import com.lmax.disruptor.BlockingWaitStrategy;
 import com.lmax.disruptor.BusySpinWaitStrategy;
 import com.lmax.disruptor.SleepingWaitStrategy;
-import com.lmax.disruptor.TimeoutBlockingWaitStrategy;
 import com.lmax.disruptor.WaitStrategy;
 import com.lmax.disruptor.YieldingWaitStrategy;
 import org.apache.logging.log4j.Logger;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java
index 4924202de0..4b45dc1e35 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java
@@ -17,23 +17,17 @@
 
 package org.apache.logging.log4j.core.async;
 
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-import com.lmax.disruptor.BlockingWaitStrategy;
-import com.lmax.disruptor.BusySpinWaitStrategy;
 import com.lmax.disruptor.ExceptionHandler;
-import com.lmax.disruptor.SleepingWaitStrategy;
 import com.lmax.disruptor.WaitStrategy;
-import com.lmax.disruptor.YieldingWaitStrategy;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.util.Constants;
 import org.apache.logging.log4j.core.util.Integers;
 import org.apache.logging.log4j.core.util.Loader;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.PropertiesUtil;
-import org.apache.logging.log4j.util.Strings;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
 
 /**
  * Utility methods for getting Disruptor related configuration.
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryConfigTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryConfigTest.java
index d5d9471c4b..215ac7edb3 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryConfigTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryConfigTest.java
@@ -16,7 +16,6 @@
  */
 package org.apache.logging.log4j.core.async;
 
-import com.lmax.disruptor.TimeoutBlockingWaitStrategy;
 import com.lmax.disruptor.WaitStrategy;
 import com.lmax.disruptor.YieldingWaitStrategy;
 import org.apache.logging.log4j.categories.AsyncLoggers;
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryIncorrectConfigGlobalLoggersTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryIncorrectConfigGlobalLoggersTest.java
index 7533ddd782..d6122b1c4f 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryIncorrectConfigGlobalLoggersTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncWaitStrategyFactoryIncorrectConfigGlobalLoggersTest.java
@@ -16,7 +16,6 @@
  */
 package org.apache.logging.log4j.core.async;
 
-import com.lmax.disruptor.TimeoutBlockingWaitStrategy;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.categories.AsyncLoggers;
 import org.apache.logging.log4j.core.LoggerContext;