You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2018/04/09 23:06:33 UTC

logging-log4j2 git commit: [LOG4J2-2313] Update LMAX Disruptor from 3.3.7 to 3.4.1. I was getting some odd 'JVM has quit' error messages so I updated the Surefire/Failsafe Maven plugins from 2.20.1 to 2.21.0 and that seems to fix it. The Histogram class

Repository: logging-log4j2
Updated Branches:
  refs/heads/release-2.x 4b784946c -> 463041147


[LOG4J2-2313] Update LMAX Disruptor from 3.3.7 to 3.4.1. I was getting
some odd 'JVM has quit' error messages so I updated the
Surefire/Failsafe Maven plugins from 2.20.1 to 2.21.0 and that seems to
fix it. The Histogram class from LMAX has been removed so I copied it
into our test code base, it is licensed under the Apache 2.0 license.

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/46304114
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/46304114
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/46304114

Branch: refs/heads/release-2.x
Commit: 4630411471e35a4f2f87087bd1c78a5809cbd792
Parents: 4b78494
Author: Gary Gregory <ga...@gmail.com>
Authored: Mon Apr 9 17:06:28 2018 -0600
Committer: Gary Gregory <ga...@gmail.com>
Committed: Mon Apr 9 17:06:28 2018 -0600

----------------------------------------------------------------------
 .../core/async/perftest/AbstractRunQueue.java   |   2 -
 .../log4j/core/async/perftest/Histogram.java    | 390 +++++++++++++++++++
 .../core/async/perftest/IPerfTestRunner.java    |   2 -
 .../async/perftest/MultiThreadPerfTest.java     |   2 -
 .../log4j/core/async/perftest/PerfTest.java     |   2 -
 .../log4j/core/async/perftest/RunLog4j1.java    |   2 -
 .../log4j/core/async/perftest/RunLog4j2.java    |   1 -
 .../log4j/core/async/perftest/RunLogback.java   |   2 -
 pom.xml                                         |   6 +-
 src/changes/changes.xml                         |   3 +
 10 files changed, 396 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/46304114/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/AbstractRunQueue.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/AbstractRunQueue.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/AbstractRunQueue.java
index 82d6065..7ba9412 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/AbstractRunQueue.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/AbstractRunQueue.java
@@ -21,8 +21,6 @@ import java.util.concurrent.BlockingQueue;
 
 import org.apache.logging.log4j.core.async.perftest.ResponseTimeTest.PrintingAsyncQueueFullPolicy;
 
-import com.lmax.disruptor.collections.Histogram;
-
 public abstract class AbstractRunQueue implements IPerfTestRunner {
 
     abstract BlockingQueue<String> createQueue(int capacity);

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/46304114/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/Histogram.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/Histogram.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/Histogram.java
new file mode 100644
index 0000000..bf0823b
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/Histogram.java
@@ -0,0 +1,390 @@
+/*
+ * 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.perftest;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Arrays;
+
+/**
+ * <p>Histogram for tracking the frequency of observations of values below interval upper bounds.</p>
+ *
+ * <p>This class is useful for recording timings across a large number of observations
+ * when high performance is required.</p>
+ *
+ * <p>The interval bounds are used to define the ranges of the histogram buckets. If provided bounds
+ * are [10,20,30,40,50] then there will be five buckets, accessible by index 0-4. Any value
+ * 0-10 will fall into the first interval bar, values 11-20 will fall into the
+ * second bar, and so on.</p>
+ */
+@Deprecated
+public final class Histogram
+{
+    // tracks the upper intervals of each of the buckets/bars
+    private final long[] upperBounds;
+    // tracks the count of the corresponding bucket
+    private final long[] counts;
+    // minimum value so far observed
+    private long minValue = Long.MAX_VALUE;
+    // maximum value so far observed
+    private long maxValue = 0L;
+
+    /**
+     * Create a new Histogram with a provided list of interval bounds.
+     *
+     * @param upperBounds of the intervals. Bounds must be provided in order least to greatest, and
+     *                    lowest bound must be greater than or equal to 1.
+     * @throws IllegalArgumentException if any of the upper bounds are less than or equal to zero
+     * @throws IllegalArgumentException if the bounds are not in order, least to greatest
+     */
+    public Histogram(final long[] upperBounds)
+    {
+        validateBounds(upperBounds);
+
+        this.upperBounds = Arrays.copyOf(upperBounds, upperBounds.length);
+        this.counts = new long[upperBounds.length];
+    }
+
+    /**
+     * Validates the input bounds; used by constructor only.
+     */
+    private void validateBounds(final long[] upperBounds)
+    {
+        long lastBound = -1L;
+        if (upperBounds.length <= 0)
+        {
+            throw new IllegalArgumentException("Must provide at least one interval");
+        }
+        for (final long bound : upperBounds)
+        {
+            if (bound <= 0L)
+            {
+                throw new IllegalArgumentException("Bounds must be positive values");
+            }
+
+            if (bound <= lastBound)
+            {
+                throw new IllegalArgumentException("bound " + bound + " is not greater than " + lastBound);
+            }
+
+            lastBound = bound;
+        }
+    }
+
+    /**
+     * Size of the list of interval bars (ie: count of interval bars).
+     *
+     * @return size of the interval bar list.
+     */
+    public int getSize()
+    {
+        return upperBounds.length;
+    }
+
+    /**
+     * Get the upper bound of an interval for an index.
+     *
+     * @param index of the upper bound.
+     * @return the interval upper bound for the index.
+     */
+    public long getUpperBoundAt(final int index)
+    {
+        return upperBounds[index];
+    }
+
+    /**
+     * Get the count of observations at a given index.
+     *
+     * @param index of the observations counter.
+     * @return the count of observations at a given index.
+     */
+    public long getCountAt(final int index)
+    {
+        return counts[index];
+    }
+
+    /**
+     * Add an observation to the histogram and increment the counter for the interval it matches.
+     *
+     * @param value for the observation to be added.
+     * @return return true if in the range of intervals and successfully added observation; otherwise false.
+     */
+    public boolean addObservation(final long value)
+    {
+        int low = 0;
+        int high = upperBounds.length - 1;
+
+        // do a classic binary search to find the high value
+        while (low < high)
+        {
+            int mid = low + ((high - low) >> 1);
+            if (upperBounds[mid] < value)
+            {
+                low = mid + 1;
+            }
+            else
+            {
+                high = mid;
+            }
+        }
+
+        // if the binary search found an eligible bucket, increment
+        if (value <= upperBounds[high])
+        {
+            counts[high]++;
+            trackRange(value);
+
+            return true;
+        }
+
+        // otherwise value was not found
+        return false;
+    }
+
+    /**
+     * Track minimum and maximum observations
+     */
+    private void trackRange(final long value)
+    {
+        if (value < minValue)
+        {
+            minValue = value;
+        }
+
+        if (value > maxValue)
+        {
+            maxValue = value;
+        }
+    }
+
+    /**
+     * <p>Add observations from another Histogram into this one.</p>
+     *
+     * <p>Histograms must have the same intervals.</p>
+     *
+     * @param histogram from which to add the observation counts.
+     * @throws IllegalArgumentException if interval count or values do not match exactly
+     */
+    public void addObservations(final Histogram histogram)
+    {
+        // validate the intervals
+        if (upperBounds.length != histogram.upperBounds.length)
+        {
+            throw new IllegalArgumentException("Histograms must have matching intervals");
+        }
+
+        for (int i = 0, size = upperBounds.length; i < size; i++)
+        {
+            if (upperBounds[i] != histogram.upperBounds[i])
+            {
+                throw new IllegalArgumentException("Histograms must have matching intervals");
+            }
+        }
+
+        // increment all of the internal counts
+        for (int i = 0, size = counts.length; i < size; i++)
+        {
+            counts[i] += histogram.counts[i];
+        }
+
+        // refresh the minimum and maximum observation ranges
+        trackRange(histogram.minValue);
+        trackRange(histogram.maxValue);
+    }
+
+    /**
+     * Clear the list of interval counters
+     */
+    public void clear()
+    {
+        maxValue = 0L;
+        minValue = Long.MAX_VALUE;
+
+        for (int i = 0, size = counts.length; i < size; i++)
+        {
+            counts[i] = 0L;
+        }
+    }
+
+    /**
+     * Count total number of recorded observations.
+     *
+     * @return the total number of recorded observations.
+     */
+    public long getCount()
+    {
+        long count = 0L;
+
+        for (int i = 0, size = counts.length; i < size; i++)
+        {
+            count += counts[i];
+        }
+
+        return count;
+    }
+
+    /**
+     * Get the minimum observed value.
+     *
+     * @return the minimum value observed.
+     */
+    public long getMin()
+    {
+        return minValue;
+    }
+
+    /**
+     * Get the maximum observed value.
+     *
+     * @return the maximum of the observed values;
+     */
+    public long getMax()
+    {
+        return maxValue;
+    }
+
+    /**
+     * <p>Calculate the mean of all recorded observations.</p>
+     *
+     * <p>The mean is calculated by summing the mid points of each interval multiplied by the count
+     * for that interval, then dividing by the total count of observations.  The max and min are
+     * considered for adjusting the top and bottom bin when calculating the mid point, this
+     * minimises skew if the observed values are very far away from the possible histogram values.</p>
+     *
+     * @return the mean of all recorded observations.
+     */
+    public BigDecimal getMean()
+    {
+        // early exit to avoid divide by zero later
+        if (0L == getCount())
+        {
+            return BigDecimal.ZERO;
+        }
+
+        // precalculate the initial lower bound; needed in the loop
+        long lowerBound = counts[0] > 0L ? minValue : 0L;
+        // use BigDecimal to avoid precision errors
+        BigDecimal total = BigDecimal.ZERO;
+
+        // midpoint is calculated as the average between the lower and upper bound
+        // (after taking into account the min & max values seen)
+        // then, simply multiply midpoint by the count of values at the interval (intervalTotal)
+        // and add to running total (total)
+        for (int i = 0, size = upperBounds.length; i < size; i++)
+        {
+            if (0L != counts[i])
+            {
+                long upperBound = Math.min(upperBounds[i], maxValue);
+                long midPoint = lowerBound + ((upperBound - lowerBound) / 2L);
+
+                BigDecimal intervalTotal = new BigDecimal(midPoint).multiply(new BigDecimal(counts[i]));
+                total = total.add(intervalTotal);
+            }
+
+            // and recalculate the lower bound for the next time around the loop
+            lowerBound = Math.max(upperBounds[i] + 1L, minValue);
+        }
+
+        return total.divide(new BigDecimal(getCount()), 2, RoundingMode.HALF_UP);
+    }
+
+    /**
+     * Calculate the upper bound within which 99% of observations fall.
+     *
+     * @return the upper bound for 99% of observations.
+     */
+    public long getTwoNinesUpperBound()
+    {
+        return getUpperBoundForFactor(0.99d);
+    }
+
+    /**
+     * Calculate the upper bound within which 99.99% of observations fall.
+     *
+     * @return the upper bound for 99.99% of observations.
+     */
+    public long getFourNinesUpperBound()
+    {
+        return getUpperBoundForFactor(0.9999d);
+    }
+
+    /**
+     * <p>Get the interval upper bound for a given factor of the observation population.</p>
+     *
+     * <p>Note this does not get the actual percentile measurement, it only gets the bucket</p>
+     *
+     * @param factor representing the size of the population.
+     * @return the interval upper bound.
+     * @throws IllegalArgumentException if factor &lt; 0.0 or factor &gt; 1.0
+     */
+    public long getUpperBoundForFactor(final double factor)
+    {
+        if (0.0d >= factor || factor >= 1.0d)
+        {
+            throw new IllegalArgumentException("factor must be >= 0.0 and <= 1.0");
+        }
+
+        final long totalCount = getCount();
+        final long tailTotal = totalCount - Math.round(totalCount * factor);
+        long tailCount = 0L;
+
+        // reverse search the intervals ('tailCount' from end)
+        for (int i = counts.length - 1; i >= 0; i--)
+        {
+            if (0L != counts[i])
+            {
+                tailCount += counts[i];
+                if (tailCount >= tailTotal)
+                {
+                    return upperBounds[i];
+                }
+            }
+        }
+
+        return 0L;
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append("Histogram{");
+
+        sb.append("min=").append(getMin()).append(", ");
+        sb.append("max=").append(getMax()).append(", ");
+        sb.append("mean=").append(getMean()).append(", ");
+        sb.append("99%=").append(getTwoNinesUpperBound()).append(", ");
+        sb.append("99.99%=").append(getFourNinesUpperBound()).append(", ");
+
+        sb.append('[');
+        for (int i = 0, size = counts.length; i < size; i++)
+        {
+            sb.append(upperBounds[i]).append('=').append(counts[i]).append(", ");
+        }
+
+        if (counts.length > 0)
+        {
+            sb.setLength(sb.length() - 2);
+        }
+        sb.append(']');
+
+        sb.append('}');
+
+        return sb.toString();
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/46304114/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/IPerfTestRunner.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/IPerfTestRunner.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/IPerfTestRunner.java
index 62bec14..bdcfcde 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/IPerfTestRunner.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/IPerfTestRunner.java
@@ -16,8 +16,6 @@
  */
 package org.apache.logging.log4j.core.async.perftest;
 
-import com.lmax.disruptor.collections.Histogram;
-
 public interface IPerfTestRunner {
     String LINE100 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!\"#$%&'()-=^~|\\@`[]{};:+*,.<>/?_123456";
     String THROUGHPUT_MSG = LINE100 + LINE100 + LINE100 + LINE100

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/46304114/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/MultiThreadPerfTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/MultiThreadPerfTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/MultiThreadPerfTest.java
index 001bc64..7b10b34 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/MultiThreadPerfTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/MultiThreadPerfTest.java
@@ -19,8 +19,6 @@ package org.apache.logging.log4j.core.async.perftest;
 import java.io.File;
 import java.util.concurrent.TimeUnit;
 
-import com.lmax.disruptor.collections.Histogram;
-
 public class MultiThreadPerfTest extends PerfTest {
 
     public static void main(final String[] args) throws Exception {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/46304114/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/PerfTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/PerfTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/PerfTest.java
index 9b34955..4161a0f 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/PerfTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/PerfTest.java
@@ -24,8 +24,6 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.logging.log4j.core.util.Loader;
 
-import com.lmax.disruptor.collections.Histogram;
-
 /**
  * Single-threaded performance test. Usually invoked from PerfTestDriver as part of a series of tests.
  * <p>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/46304114/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLog4j1.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLog4j1.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLog4j1.java
index 6db549e..aca0444 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLog4j1.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLog4j1.java
@@ -19,8 +19,6 @@ package org.apache.logging.log4j.core.async.perftest;
 import org.apache.log4j.LogManager;
 import org.apache.log4j.Logger;
 
-import com.lmax.disruptor.collections.Histogram;
-
 public class RunLog4j1 implements IPerfTestRunner {
 
     final Logger LOGGER = LogManager.getLogger(getClass());

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/46304114/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLog4j2.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLog4j2.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLog4j2.java
index df2a15d..98e69a8 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLog4j2.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLog4j2.java
@@ -19,7 +19,6 @@ package org.apache.logging.log4j.core.async.perftest;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.CoreLoggerContexts;
-import com.lmax.disruptor.collections.Histogram;
 
 public class RunLog4j2 implements IPerfTestRunner {
     final Logger LOGGER = LogManager.getLogger(getClass());

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/46304114/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLogback.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLogback.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLogback.java
index aaf22c6..b812d74 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLogback.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/RunLogback.java
@@ -21,8 +21,6 @@ import org.slf4j.LoggerFactory;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.core.spi.LifeCycle;
 
-import com.lmax.disruptor.collections.Histogram;
-
 public class RunLogback implements IPerfTestRunner {
     final Logger LOGGER = (Logger) LoggerFactory.getLogger(getClass());
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/46304114/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 9504bc8..27180ab 100644
--- a/pom.xml
+++ b/pom.xml
@@ -184,7 +184,7 @@
     <jackson2Version>2.9.5</jackson2Version>
     <springVersion>3.2.18.RELEASE</springVersion>
     <flumeVersion>1.7.0</flumeVersion> <!-- Version 1.8.0 requires Java 8 -->
-    <disruptorVersion>3.3.7</disruptorVersion>
+    <disruptorVersion>3.4.1</disruptorVersion>
     <conversantDisruptorVersion>1.2.10</conversantDisruptorVersion> <!-- Version 1.2.11 requires Java 8 -->
     <mongodb2.version>2.14.3</mongodb2.version>
     <mongodb3.version>3.6.3</mongodb3.version>
@@ -196,8 +196,8 @@
     <!-- surefire.plugin.version 2.18 yields http://jira.codehaus.org/browse/SUREFIRE-1121, which is fixed in 2.18.1 -->
     <!-- surefire.plugin.version 2.19 yields https://issues.apache.org/jira/browse/SUREFIRE-1193. -->
     <!-- all versions after 2.13 yield https://issues.apache.org/jira/browse/SUREFIRE-720 -->
-    <surefire.plugin.version>2.20.1</surefire.plugin.version>
-    <failsafe.plugin.version>2.20.1</failsafe.plugin.version>
+    <surefire.plugin.version>2.21.0</surefire.plugin.version>
+    <failsafe.plugin.version>2.21.0</failsafe.plugin.version>
     <checkstyle.plugin.version>3.0.0</checkstyle.plugin.version>
     <deploy.plugin.version>2.8.2</deploy.plugin.version>
     <rat.plugin.version>0.12</rat.plugin.version>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/46304114/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 3b60f5e..c4140c8 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -49,6 +49,9 @@
       <action issue="LOG4J2-2311" dev="ggregory" type="update">
       	Update Jackson from 2.9.4 to 2.9.5.
       </action>
+      <action issue="LOG4J2-2313" dev="ggregory" type="update">
+      	Update LMAX Disruptor from 3.3.7 to 3.4.1.
+      </action>
     </release>
     <release version="2.11.0" date="2018-03-11" description="GA Release 2.11.0">
       <action issue="LOG4J2-2104" dev="rgoers" type="fix">