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 2015/08/22 14:00:13 UTC

logging-log4j2 git commit: LOG4J2-1097 renamed CustomTimeFormat to FixedTimeFormat, fixed bug, added unit tests, renamed fields & methods in benchmarks

Repository: logging-log4j2
Updated Branches:
  refs/heads/master 76212686b -> d8935c8a8


LOG4J2-1097 renamed CustomTimeFormat to FixedTimeFormat, fixed bug,
added unit tests, renamed fields & methods in benchmarks

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

Branch: refs/heads/master
Commit: d8935c8a8015caa396be554afbbd4f0190c42d8b
Parents: 7621268
Author: rpopma <rp...@apache.org>
Authored: Sat Aug 22 21:00:23 2015 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sat Aug 22 21:00:23 2015 +0900

----------------------------------------------------------------------
 .../core/util/datetime/CustomTimeFormat.java    | 292 ------------------
 .../core/util/datetime/FixedDateFormat.java     | 299 +++++++++++++++++++
 .../util/datetime/CustomTimeFormatTest.java     | 154 ----------
 .../core/util/datetime/FixedDateFormatTest.java | 203 +++++++++++++
 .../perf/jmh/ThreadsafeDateFormatBenchmark.java |  86 +++---
 .../log4j/perf/jmh/TimeFormatBenchmark.java     |  20 +-
 6 files changed, 555 insertions(+), 499 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d8935c8a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/CustomTimeFormat.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/CustomTimeFormat.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/CustomTimeFormat.java
deleted file mode 100644
index da90b44..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/CustomTimeFormat.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.logging.log4j.core.util.datetime;
-
-import java.util.Calendar;
-import java.util.Objects;
-
-/**
- * Custom time formatter that trades flexibility for performance.
- */
-public class CustomTimeFormat {
-    /**
-     * Enumeration over the supported date/time format patterns.
-     * <p>
-     * Package protected for unit tests.
-     */
-    static enum FixedFormat {
-        /**
-         * ABSOLUTE time format: {@code "HH:mm:ss,SSS"}.
-         */
-        ABSOLUTE("HH:mm:ss,SSS", null, 0, ':', 1, ',', 1),
-
-        /**
-         * ABSOLUTE time format variation with period separator: {@code "HH:mm:ss.SSS"}.
-         */
-        ABSOLUTE2("HH:mm:ss.SSS", null, 0, ':', 1, '.', 1),
-
-        /**
-         * COMPACT time format: {@code "yyyyMMddHHmmssSSS"}.
-         */
-        COMPACT("yyyyMMddHHmmssSSS", "yyyyMMdd", 0, ' ', 0, ' ', 0),
-
-        /**
-         * DATE time format: {@code "dd MMM yyyy HH:mm:ss,SSS"}.
-         */
-        DATE("dd MMM yyyy HH:mm:ss,SSS", "dd MMM yyyy ", 0, ':', 1, ',', 1),
-
-        /**
-         * DATE time format variation with period separator: {@code "dd MMM yyyy HH:mm:ss.SSS"}.
-         */
-        DATE2("dd MMM yyyy HH:mm:ss.SSS", "dd MMM yyyy ", 0, ':', 1, '.', 1),
-
-        /**
-         * DEFAULT time format: {@code "yyyy-MM-dd HH:mm:ss,SSS"}.
-         */
-        DEFAULT("yyyy-MM-dd HH:mm:ss,SSS", "yyyy-MM-dd ", 0, ':', 1, ',', 1),
-
-        /**
-         * DEFAULT time format variation with period separator: {@code "yyyy-MM-dd HH:mm:ss.SSS"}.
-         */
-        DEFAULT2("yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd ", 0, ':', 1, '.', 1),
-
-        /**
-         * ISO8601_BASIC time format: {@code "yyyyMMdd'T'HHmmss,SSS"}.
-         */
-        ISO8601_BASIC("yyyyMMdd'T'HHmmss,SSS", "yyyyMMdd'T'", 2, ' ', 0, ',', 1),
-
-        /**
-         * ISO8601 time format: {@code "yyyy-MM-dd'T'HH:mm:ss,SSS"}.
-         */
-        ISO8601("yyyy-MM-dd'T'HH:mm:ss,SSS", "yyyy-MM-dd'T'", 2, ':', 1, ',', 1), ;
-
-        private final String pattern;
-        private final String datePattern;
-        private final int escapeCount;
-        private final char timeSeparatorChar;
-        private final int timeSeparatorLength;
-        private final char millisSeparatorChar;
-        private final int millisSeparatorLength;
-
-        private FixedFormat(final String pattern, final String datePattern, final int escapeCount,
-                final char timeSeparator, final int timeSepLength, final char millisSeparator, final int millisSepLength) {
-            this.timeSeparatorChar = timeSeparator;
-            this.timeSeparatorLength = timeSepLength;
-            this.millisSeparatorChar = millisSeparator;
-            this.millisSeparatorLength = millisSepLength;
-            this.pattern = Objects.requireNonNull(pattern);
-            this.datePattern = datePattern; // may be null
-            this.escapeCount = escapeCount;
-        }
-
-        public String getPattern() {
-            return pattern;
-        }
-
-        public String getDatePattern() {
-            return datePattern;
-        }
-
-        /**
-         * Returns the FixedFormat with the name or pattern matching the specified string or {@code null} if not found.
-         */
-        public static FixedFormat lookup(final String nameOrPattern) {
-            for (final FixedFormat type : FixedFormat.values()) {
-                if (type.name().equals(nameOrPattern) || type.getPattern().equals(nameOrPattern)) {
-                    return type;
-                }
-            }
-            return null;
-        }
-
-        public int getLength() {
-            return pattern.length() - escapeCount;
-        }
-
-        public int getDatePatternLength() {
-            return getDatePattern() == null ? 0 : getDatePattern().length() - escapeCount;
-        }
-
-        public FastDateFormat getFastDateFormat() {
-            return getDatePattern() == null ? null : FastDateFormat.getInstance(getDatePattern());
-        }
-    }
-
-    public static CustomTimeFormat createIfSupported(final String... options) {
-        if (options == null || options.length == 0 || options.length > 1) {
-            return null; // time zone not supported
-        }
-        final FixedFormat type = FixedFormat.lookup(options[0]);
-        return type == null ? null : new CustomTimeFormat(type);
-    }
-
-    private final FixedFormat type;
-    private final int length;
-    private final int dateLength;
-    private final FastDateFormat fastDateFormat; // may be null
-    private final char timeSeparatorChar;
-    private final char millisSeparatorChar;
-    private final int timeSeparatorLength;
-    private final int millisSeparatorLength;
-
-    private volatile long midnightToday = 0;
-    private volatile long midnightTomorrow = 0;
-    // cachedDate does not need to be volatile because
-    // there is a write to a volatile field *after* cachedDate is modified,
-    // and there is a read from a volatile field *before* cachedDate is read.
-    // The Java memory model guarantees that because of the above,
-    // changes to cachedDate in one thread are visible to other threads.
-    // See http://g.oswego.edu/dl/jmm/cookbook.html
-    private char[] cachedDate; // may be null
-
-    /**
-     * Constructs a CustomTimeFormat for the specified fixed format.
-     * <p>
-     * Package protected for unit tests.
-     * 
-     * @param type the fixed format
-     */
-    CustomTimeFormat(final FixedFormat type) {
-        this.type = Objects.requireNonNull(type);
-        this.timeSeparatorChar = type.timeSeparatorChar;
-        this.timeSeparatorLength = type.timeSeparatorLength;
-        this.millisSeparatorChar = type.millisSeparatorChar;
-        this.millisSeparatorLength = type.millisSeparatorLength;
-        this.length = type.getLength();
-        this.dateLength = type.getDatePatternLength();
-        this.fastDateFormat = type.getFastDateFormat();
-    }
-
-    public String getFormat() {
-        return type.getPattern();
-    }
-
-    // Profiling showed this method is important to log4j performance. Modify with care!
-    // 21 bytes (allows immediate JVM inlining: <= -XX:MaxInlineSize=35 bytes)
-    private long millisSinceMidnight(final long now) {
-        if (now >= midnightTomorrow) {
-            updateMidnightMillis(now);
-        }
-        return now - midnightToday;
-    }
-
-    private void updateMidnightMillis(final long now) {
-
-        updateCachedDate(now);
-
-        midnightToday = calcMidnightMillis(now, 0);
-        midnightTomorrow = calcMidnightMillis(now, 1);
-    }
-
-    static long calcMidnightMillis(final long time, final int addDays) {
-        final Calendar cal = Calendar.getInstance();
-        cal.setTimeInMillis(time);
-        cal.set(Calendar.HOUR_OF_DAY, 0);
-        cal.set(Calendar.MINUTE, 0);
-        cal.set(Calendar.SECOND, 0);
-        cal.set(Calendar.MILLISECOND, 0);
-        cal.add(Calendar.DATE, addDays);
-        return cal.getTimeInMillis();
-    }
-
-    private void updateCachedDate(final long now) {
-        if (fastDateFormat != null) {
-            final StringBuilder result = fastDateFormat.format(now, new StringBuilder());
-            cachedDate = result.toString().toCharArray();
-        }
-    }
-
-    // Profiling showed this method is important to log4j performance. Modify with care!
-    // 28 bytes (allows immediate JVM inlining: <= -XX:MaxInlineSize=35 bytes)
-    public String format(final long time) {
-        final char[] result = new char[length];
-        int written = format(time, result, 0);
-        return new String(result, 0, written);
-    }
-
-    // Profiling showed this method is important to log4j performance. Modify with care!
-    // 31 bytes (allows immediate JVM inlining: <= -XX:MaxInlineSize=35 bytes)
-    public int format(final long time, final char[] buffer, final int startPos) {
-        // Calculate values by getting the ms values first and do then
-        // calculate the hour minute and second values divisions.
-
-        // Get daytime in ms: this does fit into an int
-        // int ms = (int) (time % 86400000);
-        final int ms = (int) (millisSinceMidnight(time));
-        writeDate(buffer, startPos);
-        return writeTime(ms, buffer, startPos + dateLength) - startPos;
-    }
-
-    // Profiling showed this method is important to log4j performance. Modify with care!
-    // 22 bytes (allows immediate JVM inlining: <= -XX:MaxInlineSize=35 bytes)
-    private void writeDate(final char[] buffer, final int startPos) {
-        if (cachedDate != null) {
-            System.arraycopy(cachedDate, 0, buffer, startPos, dateLength);
-        }
-    }
-
-    // Profiling showed this method is important to log4j performance. Modify with care!
-    // 262 bytes (will be inlined when hot enough: <= -XX:FreqInlineSize=325 bytes on Linux)
-    private int writeTime(int ms, final char[] buffer, int pos) {
-        final int hours = ms / 3600000;
-        ms -= 3600000 * hours;
-
-        final int minutes = ms / 60000;
-        ms -= 60000 * minutes;
-
-        final int seconds = ms / 1000;
-        ms -= 1000 * seconds;
-
-        // Hour
-        int temp = hours / 10;
-        buffer[pos++] = ((char) (temp + '0'));
-
-        // Do subtract to get remainder instead of doing % 10
-        buffer[pos++] = ((char) (hours - 10 * temp + '0'));
-        buffer[pos] = timeSeparatorChar;
-        pos += timeSeparatorLength;
-
-        // Minute
-        temp = minutes / 10;
-        buffer[pos++] = ((char) (temp + '0'));
-
-        // Do subtract to get remainder instead of doing % 10
-        buffer[pos++] = ((char) (minutes - 10 * temp + '0'));
-        buffer[pos] = timeSeparatorChar;
-        pos += timeSeparatorLength;
-
-        // Second
-        temp = seconds / 10;
-        buffer[pos++] = ((char) (temp + '0'));
-        buffer[pos++] = ((char) (seconds - 10 * temp + '0'));
-        buffer[pos] = millisSeparatorChar;
-        pos += millisSeparatorLength;
-
-        // Millisecond
-        temp = ms / 100;
-        buffer[pos++] = ((char) (temp + '0'));
-
-        ms -= 100 * temp;
-        temp = ms / 10;
-        buffer[pos++] = ((char) (temp + '0'));
-
-        ms -= 10 * temp;
-        buffer[pos++] = ((char) (ms + '0'));
-        return pos;
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d8935c8a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FixedDateFormat.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FixedDateFormat.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FixedDateFormat.java
new file mode 100644
index 0000000..b65fb2b
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FixedDateFormat.java
@@ -0,0 +1,299 @@
+/*
+ * 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.
+ */
+
+package org.apache.logging.log4j.core.util.datetime;
+
+import java.util.Calendar;
+import java.util.Objects;
+
+/**
+ * Custom time formatter that trades flexibility for performance.
+ */
+public class FixedDateFormat {
+    /**
+     * Enumeration over the supported date/time format patterns.
+     * <p>
+     * Package protected for unit tests.
+     */
+    public static enum FixedFormat {
+        /**
+         * ABSOLUTE time format: {@code "HH:mm:ss,SSS"}.
+         */
+        ABSOLUTE("HH:mm:ss,SSS", null, 0, ':', 1, ',', 1),
+
+        /**
+         * ABSOLUTE time format variation with period separator: {@code "HH:mm:ss.SSS"}.
+         */
+        ABSOLUTE_PERIOD("HH:mm:ss.SSS", null, 0, ':', 1, '.', 1),
+
+        /**
+         * COMPACT time format: {@code "yyyyMMddHHmmssSSS"}.
+         */
+        COMPACT("yyyyMMddHHmmssSSS", "yyyyMMdd", 0, ' ', 0, ' ', 0),
+
+        /**
+         * DATE_AND_TIME time format: {@code "dd MMM yyyy HH:mm:ss,SSS"}.
+         */
+        DATE("dd MMM yyyy HH:mm:ss,SSS", "dd MMM yyyy ", 0, ':', 1, ',', 1),
+
+        /**
+         * DATE_AND_TIME time format variation with period separator: {@code "dd MMM yyyy HH:mm:ss.SSS"}.
+         */
+        DATE_PERIOD("dd MMM yyyy HH:mm:ss.SSS", "dd MMM yyyy ", 0, ':', 1, '.', 1),
+
+        /**
+         * DEFAULT time format: {@code "yyyy-MM-dd HH:mm:ss,SSS"}.
+         */
+        DEFAULT("yyyy-MM-dd HH:mm:ss,SSS", "yyyy-MM-dd ", 0, ':', 1, ',', 1),
+
+        /**
+         * DEFAULT time format variation with period separator: {@code "yyyy-MM-dd HH:mm:ss.SSS"}.
+         */
+        DEFAULT_PERIOD("yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd ", 0, ':', 1, '.', 1),
+
+        /**
+         * ISO8601_BASIC time format: {@code "yyyyMMdd'T'HHmmss,SSS"}.
+         */
+        ISO8601_BASIC("yyyyMMdd'T'HHmmss,SSS", "yyyyMMdd'T'", 2, ' ', 0, ',', 1),
+
+        /**
+         * ISO8601 time format: {@code "yyyy-MM-dd'T'HH:mm:ss,SSS"}.
+         */
+        ISO8601("yyyy-MM-dd'T'HH:mm:ss,SSS", "yyyy-MM-dd'T'", 2, ':', 1, ',', 1), ;
+
+        private final String pattern;
+        private final String datePattern;
+        private final int escapeCount;
+        private final char timeSeparatorChar;
+        private final int timeSeparatorLength;
+        private final char millisSeparatorChar;
+        private final int millisSeparatorLength;
+
+        private FixedFormat(final String pattern, final String datePattern, final int escapeCount,
+                final char timeSeparator, final int timeSepLength, final char millisSeparator, final int millisSepLength) {
+            this.timeSeparatorChar = timeSeparator;
+            this.timeSeparatorLength = timeSepLength;
+            this.millisSeparatorChar = millisSeparator;
+            this.millisSeparatorLength = millisSepLength;
+            this.pattern = Objects.requireNonNull(pattern);
+            this.datePattern = datePattern; // may be null
+            this.escapeCount = escapeCount;
+        }
+
+        public String getPattern() {
+            return pattern;
+        }
+
+        public String getDatePattern() {
+            return datePattern;
+        }
+
+        /**
+         * Returns the FixedFormat with the name or pattern matching the specified string or {@code null} if not found.
+         */
+        public static FixedFormat lookup(final String nameOrPattern) {
+            for (final FixedFormat type : FixedFormat.values()) {
+                if (type.name().equals(nameOrPattern) || type.getPattern().equals(nameOrPattern)) {
+                    return type;
+                }
+            }
+            return null;
+        }
+
+        public int getLength() {
+            return pattern.length() - escapeCount;
+        }
+
+        public int getDatePatternLength() {
+            return getDatePattern() == null ? 0 : getDatePattern().length() - escapeCount;
+        }
+
+        public FastDateFormat getFastDateFormat() {
+            return getDatePattern() == null ? null : FastDateFormat.getInstance(getDatePattern());
+        }
+    }
+
+    public static FixedDateFormat createIfSupported(final String... options) {
+        if (options == null || options.length == 0 || options[0] == null) {
+            return new FixedDateFormat(FixedFormat.DEFAULT);
+        }
+        if (options.length > 1) {
+            return null; // time zone not supported
+        }
+        final FixedFormat type = FixedFormat.lookup(options[0]);
+        return type == null ? null : new FixedDateFormat(type);
+    }
+    
+    public static FixedDateFormat create(FixedFormat format) {
+        return new FixedDateFormat(format);
+    }
+
+    private final FixedFormat fixedFormat;
+    private final int length;
+    private final int dateLength;
+    private final FastDateFormat fastDateFormat; // may be null
+    private final char timeSeparatorChar;
+    private final char millisSeparatorChar;
+    private final int timeSeparatorLength;
+    private final int millisSeparatorLength;
+
+    private volatile long midnightToday = 0;
+    private volatile long midnightTomorrow = 0;
+    // cachedDate does not need to be volatile because
+    // there is a write to a volatile field *after* cachedDate is modified,
+    // and there is a read from a volatile field *before* cachedDate is read.
+    // The Java memory model guarantees that because of the above,
+    // changes to cachedDate in one thread are visible to other threads.
+    // See http://g.oswego.edu/dl/jmm/cookbook.html
+    private char[] cachedDate; // may be null
+
+    /**
+     * Constructs a FixedDateFormat for the specified fixed format.
+     * <p>
+     * Package protected for unit tests.
+     * 
+     * @param fixedFormat the fixed format
+     */
+    FixedDateFormat(final FixedFormat fixedFormat) {
+        this.fixedFormat = Objects.requireNonNull(fixedFormat);
+        this.timeSeparatorChar = fixedFormat.timeSeparatorChar;
+        this.timeSeparatorLength = fixedFormat.timeSeparatorLength;
+        this.millisSeparatorChar = fixedFormat.millisSeparatorChar;
+        this.millisSeparatorLength = fixedFormat.millisSeparatorLength;
+        this.length = fixedFormat.getLength();
+        this.dateLength = fixedFormat.getDatePatternLength();
+        this.fastDateFormat = fixedFormat.getFastDateFormat();
+    }
+
+    public String getFormat() {
+        return fixedFormat.getPattern();
+    }
+
+    // Profiling showed this method is important to log4j performance. Modify with care!
+    // 30 bytes (allows immediate JVM inlining: <= -XX:MaxInlineSize=35 bytes)
+    private long millisSinceMidnight(final long now) {
+        if (now >= midnightTomorrow || now < midnightToday) {
+            updateMidnightMillis(now);
+        }
+        return now - midnightToday;
+    }
+
+    private void updateMidnightMillis(final long now) {
+
+        updateCachedDate(now);
+
+        midnightToday = calcMidnightMillis(now, 0);
+        midnightTomorrow = calcMidnightMillis(now, 1);
+    }
+
+    static long calcMidnightMillis(final long time, final int addDays) {
+        final Calendar cal = Calendar.getInstance();
+        cal.setTimeInMillis(time);
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        cal.add(Calendar.DATE, addDays);
+        return cal.getTimeInMillis();
+    }
+
+    private void updateCachedDate(final long now) {
+        if (fastDateFormat != null) {
+            final StringBuilder result = fastDateFormat.format(now, new StringBuilder());
+            cachedDate = result.toString().toCharArray();
+        }
+    }
+
+    // Profiling showed this method is important to log4j performance. Modify with care!
+    // 28 bytes (allows immediate JVM inlining: <= -XX:MaxInlineSize=35 bytes)
+    public String format(final long time) {
+        final char[] result = new char[length];
+        int written = format(time, result, 0);
+        return new String(result, 0, written);
+    }
+
+    // Profiling showed this method is important to log4j performance. Modify with care!
+    // 31 bytes (allows immediate JVM inlining: <= -XX:MaxInlineSize=35 bytes)
+    public int format(final long time, final char[] buffer, final int startPos) {
+        // Calculate values by getting the ms values first and do then
+        // calculate the hour minute and second values divisions.
+
+        // Get daytime in ms: this does fit into an int
+        // int ms = (int) (time % 86400000);
+        final int ms = (int) (millisSinceMidnight(time));
+        writeDate(buffer, startPos);
+        return writeTime(ms, buffer, startPos + dateLength) - startPos;
+    }
+
+    // Profiling showed this method is important to log4j performance. Modify with care!
+    // 22 bytes (allows immediate JVM inlining: <= -XX:MaxInlineSize=35 bytes)
+    private void writeDate(final char[] buffer, final int startPos) {
+        if (cachedDate != null) {
+            System.arraycopy(cachedDate, 0, buffer, startPos, dateLength);
+        }
+    }
+
+    // Profiling showed this method is important to log4j performance. Modify with care!
+    // 262 bytes (will be inlined when hot enough: <= -XX:FreqInlineSize=325 bytes on Linux)
+    private int writeTime(int ms, final char[] buffer, int pos) {
+        final int hours = ms / 3600000;
+        ms -= 3600000 * hours;
+
+        final int minutes = ms / 60000;
+        ms -= 60000 * minutes;
+
+        final int seconds = ms / 1000;
+        ms -= 1000 * seconds;
+
+        // Hour
+        int temp = hours / 10;
+        buffer[pos++] = ((char) (temp + '0'));
+
+        // Do subtract to get remainder instead of doing % 10
+        buffer[pos++] = ((char) (hours - 10 * temp + '0'));
+        buffer[pos] = timeSeparatorChar;
+        pos += timeSeparatorLength;
+
+        // Minute
+        temp = minutes / 10;
+        buffer[pos++] = ((char) (temp + '0'));
+
+        // Do subtract to get remainder instead of doing % 10
+        buffer[pos++] = ((char) (minutes - 10 * temp + '0'));
+        buffer[pos] = timeSeparatorChar;
+        pos += timeSeparatorLength;
+
+        // Second
+        temp = seconds / 10;
+        buffer[pos++] = ((char) (temp + '0'));
+        buffer[pos++] = ((char) (seconds - 10 * temp + '0'));
+        buffer[pos] = millisSeparatorChar;
+        pos += millisSeparatorLength;
+
+        // Millisecond
+        temp = ms / 100;
+        buffer[pos++] = ((char) (temp + '0'));
+
+        ms -= 100 * temp;
+        temp = ms / 10;
+        buffer[pos++] = ((char) (temp + '0'));
+
+        ms -= 10 * temp;
+        buffer[pos++] = ((char) (ms + '0'));
+        return pos;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d8935c8a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/datetime/CustomTimeFormatTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/datetime/CustomTimeFormatTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/datetime/CustomTimeFormatTest.java
deleted file mode 100644
index be674c1..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/datetime/CustomTimeFormatTest.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.logging.log4j.core.util.datetime;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.logging.log4j.core.util.datetime.CustomTimeFormat.FixedFormat;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-/**
- * Tests the CustomTimeFormat class.
- */
-public class CustomTimeFormatTest {
-
-    @Test
-    public void testFixedFormat_getDatePatternNullIfNoDateInPattern() {
-        assertNull(FixedFormat.ABSOLUTE.getDatePattern());
-        assertNull(FixedFormat.ABSOLUTE2.getDatePattern());
-    }
-
-    @Test
-    public void testFixedFormat_getDatePatternLengthZeroIfNoDateInPattern() {
-        assertEquals(0, FixedFormat.ABSOLUTE.getDatePatternLength());
-        assertEquals(0, FixedFormat.ABSOLUTE2.getDatePatternLength());
-    }
-
-    @Test
-    public void testFixedFormat_getFastDateFormatNullIfNoDateInPattern() {
-        assertNull(FixedFormat.ABSOLUTE.getFastDateFormat());
-        assertNull(FixedFormat.ABSOLUTE2.getFastDateFormat());
-    }
-
-    @Test
-    public void testFixedFormat_getDatePatternReturnsDatePatternIfExists() {
-        assertEquals("yyyyMMdd", FixedFormat.COMPACT.getDatePattern());
-        assertEquals("yyyy-MM-dd ", FixedFormat.DEFAULT.getDatePattern());
-    }
-
-    @Test
-    public void testFixedFormat_getDatePatternLengthReturnsDatePatternLength() {
-        assertEquals("yyyyMMdd".length(), FixedFormat.COMPACT.getDatePatternLength());
-        assertEquals("yyyy-MM-dd ".length(), FixedFormat.DEFAULT.getDatePatternLength());
-    }
-
-    @Test
-    public void testFixedFormat_getFastDateFormatNonNullIfDateInPattern() {
-        assertNotNull(FixedFormat.COMPACT.getFastDateFormat());
-        assertNotNull(FixedFormat.DEFAULT.getFastDateFormat());
-        assertEquals("yyyyMMdd", FixedFormat.COMPACT.getFastDateFormat().getPattern());
-        assertEquals("yyyy-MM-dd ", FixedFormat.DEFAULT.getFastDateFormat().getPattern());
-    }
-    
-    @Test
-    public void testCreateIfSupported_nonNullIfNameMatches() {
-        for (final CustomTimeFormat.FixedFormat format : CustomTimeFormat.FixedFormat.values()) {
-            final String[] options = {format.name()};
-            assertNotNull(format.name(), CustomTimeFormat.createIfSupported(options));
-        }
-    }
-
-    @Test
-    public void testCreateIfSupported_nonNullIfPatternMatches() {
-        for (final CustomTimeFormat.FixedFormat format : CustomTimeFormat.FixedFormat.values()) {
-            final String[] options = {format.getPattern()};
-            assertNotNull(format.name(), CustomTimeFormat.createIfSupported(options));
-        }
-    }
-
-    @Test
-    public void testCreateIfSupported_nullIfNameDoesNotMatch() {
-        final String[] options = {"DEFAULT3"};
-        assertNull("DEFAULT3", CustomTimeFormat.createIfSupported(options));
-    }
-
-    @Test
-    public void testCreateIfSupported_nullIfPatternDoesNotMatch() {
-        final String[] options = {"y M d H m s"};
-        assertNull("y M d H m s", CustomTimeFormat.createIfSupported(options));
-    }
-
-    @Test
-    public void testCreateIfSupported_nullIfOptionsArrayNull() {
-        assertNull("null", CustomTimeFormat.createIfSupported((String[]) null));
-    }
-
-    @Test
-    public void testCreateIfSupported_nullIfOptionsArrayHasTwoElements() {
-        final String[] options = {CustomTimeFormat.FixedFormat.ABSOLUTE.getPattern(), "+08:00"};
-        assertNull("timezone", CustomTimeFormat.createIfSupported(options));
-    }
-
-    @Test(expected=NullPointerException.class)
-    public void testConstructorDisallowsNull() {
-        new CustomTimeFormat(null);
-    }
-
-    @Test
-    public void testGetFormatReturnsConstructorFixedFormatPattern() {
-        final CustomTimeFormat format = new CustomTimeFormat(CustomTimeFormat.FixedFormat.ABSOLUTE);
-        assertSame(CustomTimeFormat.FixedFormat.ABSOLUTE.getPattern(), format.getFormat());
-    }
-
-    @Test
-    public void testFormatLong() {
-        final long start = System.currentTimeMillis();
-        final long end = start + TimeUnit.HOURS.toMillis(25);
-        for (final FixedFormat format : FixedFormat.values()) {
-            final SimpleDateFormat simpleDF = new SimpleDateFormat(format.getPattern());
-            final CustomTimeFormat customTF = new CustomTimeFormat(format);
-            for (long time = start; time < end; time += 12345) {
-                final String actual = customTF.format(time);
-                final String expected = simpleDF.format(new Date(time));
-                assertEquals(format + "/" + time, expected, actual);
-            }
-        }
-    }
-
-    @Test
-    public void testFormatLongCharArrayInt() {
-        final long start = System.currentTimeMillis();
-        final long end = start + TimeUnit.HOURS.toMillis(25);
-        final char[] buffer = new char[128];
-        for (final FixedFormat format : FixedFormat.values()) {
-            final SimpleDateFormat simpleDF = new SimpleDateFormat(format.getPattern());
-            final CustomTimeFormat customTF = new CustomTimeFormat(format);
-            for (long time = start; time < end; time += 12345) {
-                final int length = customTF.format(time, buffer, 23);
-                final String actual = new String(buffer, 23, length);
-                final String expected = simpleDF.format(new Date(time));
-                assertEquals(format + "/" + time, expected, actual);
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d8935c8a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/datetime/FixedDateFormatTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/datetime/FixedDateFormatTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/datetime/FixedDateFormatTest.java
new file mode 100644
index 0000000..dc222e7
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/datetime/FixedDateFormatTest.java
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+package org.apache.logging.log4j.core.util.datetime;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.logging.log4j.core.util.datetime.FixedDateFormat.FixedFormat;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests the FixedDateFormat class.
+ */
+public class FixedDateFormatTest {
+
+    @Test
+    public void testFixedFormat_getDatePatternNullIfNoDateInPattern() {
+        assertNull(FixedFormat.ABSOLUTE.getDatePattern());
+        assertNull(FixedFormat.ABSOLUTE_PERIOD.getDatePattern());
+    }
+
+    @Test
+    public void testFixedFormat_getDatePatternLengthZeroIfNoDateInPattern() {
+        assertEquals(0, FixedFormat.ABSOLUTE.getDatePatternLength());
+        assertEquals(0, FixedFormat.ABSOLUTE_PERIOD.getDatePatternLength());
+    }
+
+    @Test
+    public void testFixedFormat_getFastDateFormatNullIfNoDateInPattern() {
+        assertNull(FixedFormat.ABSOLUTE.getFastDateFormat());
+        assertNull(FixedFormat.ABSOLUTE_PERIOD.getFastDateFormat());
+    }
+
+    @Test
+    public void testFixedFormat_getDatePatternReturnsDatePatternIfExists() {
+        assertEquals("yyyyMMdd", FixedFormat.COMPACT.getDatePattern());
+        assertEquals("yyyy-MM-dd ", FixedFormat.DEFAULT.getDatePattern());
+    }
+
+    @Test
+    public void testFixedFormat_getDatePatternLengthReturnsDatePatternLength() {
+        assertEquals("yyyyMMdd".length(), FixedFormat.COMPACT.getDatePatternLength());
+        assertEquals("yyyy-MM-dd ".length(), FixedFormat.DEFAULT.getDatePatternLength());
+    }
+
+    @Test
+    public void testFixedFormat_getFastDateFormatNonNullIfDateInPattern() {
+        assertNotNull(FixedFormat.COMPACT.getFastDateFormat());
+        assertNotNull(FixedFormat.DEFAULT.getFastDateFormat());
+        assertEquals("yyyyMMdd", FixedFormat.COMPACT.getFastDateFormat().getPattern());
+        assertEquals("yyyy-MM-dd ", FixedFormat.DEFAULT.getFastDateFormat().getPattern());
+    }
+    
+    @Test
+    public void testCreateIfSupported_nonNullIfNameMatches() {
+        for (final FixedDateFormat.FixedFormat format : FixedDateFormat.FixedFormat.values()) {
+            final String[] options = {format.name()};
+            assertNotNull(format.name(), FixedDateFormat.createIfSupported(options));
+        }
+    }
+
+    @Test
+    public void testCreateIfSupported_nonNullIfPatternMatches() {
+        for (final FixedDateFormat.FixedFormat format : FixedDateFormat.FixedFormat.values()) {
+            final String[] options = {format.getPattern()};
+            assertNotNull(format.name(), FixedDateFormat.createIfSupported(options));
+        }
+    }
+
+    @Test
+    public void testCreateIfSupported_nullIfNameDoesNotMatch() {
+        final String[] options = {"DEFAULT3"};
+        assertNull("DEFAULT3", FixedDateFormat.createIfSupported(options));
+    }
+
+    @Test
+    public void testCreateIfSupported_nullIfPatternDoesNotMatch() {
+        final String[] options = {"y M d H m s"};
+        assertNull("y M d H m s", FixedDateFormat.createIfSupported(options));
+    }
+
+    @Test
+    public void testCreateIfSupported_defaultIfOptionsArrayNull() {
+        final FixedDateFormat fmt = FixedDateFormat.createIfSupported((String[]) null);
+        assertEquals(FixedFormat.DEFAULT.getPattern(), fmt.getFormat());
+    }
+
+    @Test
+    public void testCreateIfSupported_defaultIfOptionsArrayEmpty() {
+        final FixedDateFormat fmt = FixedDateFormat.createIfSupported(new String[0]);
+        assertEquals(FixedFormat.DEFAULT.getPattern(), fmt.getFormat());
+    }
+
+    @Test
+    public void testCreateIfSupported_defaultIfOptionsArrayWithSingleNullElement() {
+        final FixedDateFormat fmt = FixedDateFormat.createIfSupported(new String[1]);
+        assertEquals(FixedFormat.DEFAULT.getPattern(), fmt.getFormat());
+    }
+
+    @Test
+    public void testCreateIfSupported_nullIfOptionsArrayHasTwoElements() {
+        final String[] options = {FixedDateFormat.FixedFormat.ABSOLUTE.getPattern(), "+08:00"};
+        assertNull("timezone", FixedDateFormat.createIfSupported(options));
+    }
+
+    @Test(expected=NullPointerException.class)
+    public void testConstructorDisallowsNull() {
+        new FixedDateFormat(null);
+    }
+
+    @Test
+    public void testGetFormatReturnsConstructorFixedFormatPattern() {
+        final FixedDateFormat format = new FixedDateFormat(FixedDateFormat.FixedFormat.ABSOLUTE);
+        assertSame(FixedDateFormat.FixedFormat.ABSOLUTE.getPattern(), format.getFormat());
+    }
+
+    @Test
+    public void testFormatLong() {
+        final long now = System.currentTimeMillis();
+        final long start = now - TimeUnit.HOURS.toMillis(25);
+        final long end = now + TimeUnit.HOURS.toMillis(25);
+        for (final FixedFormat format : FixedFormat.values()) {
+            final SimpleDateFormat simpleDF = new SimpleDateFormat(format.getPattern());
+            final FixedDateFormat customTF = new FixedDateFormat(format);
+            for (long time = start; time < end; time += 12345) {
+                final String actual = customTF.format(time);
+                final String expected = simpleDF.format(new Date(time));
+                assertEquals(format + "/" + time, expected, actual);
+            }
+        }
+    }
+
+    @Test
+    public void testFormatLong_goingBackInTime() {
+        final long now = System.currentTimeMillis();
+        final long start = now - TimeUnit.HOURS.toMillis(25);
+        final long end = now + TimeUnit.HOURS.toMillis(25);
+        for (final FixedFormat format : FixedFormat.values()) {
+            final SimpleDateFormat simpleDF = new SimpleDateFormat(format.getPattern());
+            final FixedDateFormat customTF = new FixedDateFormat(format);
+            for (long time = end; time > start; time -= 12345) {
+                final String actual = customTF.format(time);
+                final String expected = simpleDF.format(new Date(time));
+                assertEquals(format + "/" + time, expected, actual);
+            }
+        }
+    }
+
+    @Test
+    public void testFormatLongCharArrayInt() {
+        final long now = System.currentTimeMillis();
+        final long start = now - TimeUnit.HOURS.toMillis(25);
+        final long end = now + TimeUnit.HOURS.toMillis(25);
+        final char[] buffer = new char[128];
+        for (final FixedFormat format : FixedFormat.values()) {
+            final SimpleDateFormat simpleDF = new SimpleDateFormat(format.getPattern());
+            final FixedDateFormat customTF = new FixedDateFormat(format);
+            for (long time = start; time < end; time += 12345) {
+                final int length = customTF.format(time, buffer, 23);
+                final String actual = new String(buffer, 23, length);
+                final String expected = simpleDF.format(new Date(time));
+                assertEquals(format + "/" + time, expected, actual);
+            }
+        }
+    }
+
+    @Test
+    public void testFormatLongCharArrayInt_goingBackInTime() {
+        final long now = System.currentTimeMillis();
+        final long start = now - TimeUnit.HOURS.toMillis(25);
+        final long end = now + TimeUnit.HOURS.toMillis(25);
+        final char[] buffer = new char[128];
+        for (final FixedFormat format : FixedFormat.values()) {
+            final SimpleDateFormat simpleDF = new SimpleDateFormat(format.getPattern());
+            final FixedDateFormat customTF = new FixedDateFormat(format);
+            for (long time = end; time > start; time -= 12345) {
+                final int length = customTF.format(time, buffer, 23);
+                final String actual = new String(buffer, 23, length);
+                final String expected = simpleDF.format(new Date(time));
+                assertEquals(format + "/" + time, expected, actual);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d8935c8a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/ThreadsafeDateFormatBenchmark.java
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/ThreadsafeDateFormatBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/ThreadsafeDateFormatBenchmark.java
index ff06520..d6865a3 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/ThreadsafeDateFormatBenchmark.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/ThreadsafeDateFormatBenchmark.java
@@ -22,7 +22,7 @@ import java.util.Date;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 
-import org.apache.logging.log4j.core.util.datetime.CustomTimeFormat;
+import org.apache.logging.log4j.core.util.datetime.FixedDateFormat;
 import org.apache.logging.log4j.core.util.datetime.FastDateFormat;
 import org.openjdk.jmh.annotations.Benchmark;
 import org.openjdk.jmh.annotations.BenchmarkMode;
@@ -50,50 +50,50 @@ public class ThreadsafeDateFormatBenchmark {
 
     private final Date date = new Date();
     private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
-    private final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>() {
+    private final ThreadLocal<SimpleDateFormat> threadLocalSDFormat = new ThreadLocal<SimpleDateFormat>() {
         @Override
         protected SimpleDateFormat initialValue() {
             return new SimpleDateFormat("HH:mm:ss.SSS");
         }
     };
 
-    private final ThreadLocal<Formatter> localFormat = new ThreadLocal<Formatter>() {
+    private final ThreadLocal<FormatterSimple> threadLocalCachedSDFormat = new ThreadLocal<FormatterSimple>() {
         @Override
-        protected Formatter initialValue() {
-            return new Formatter();
+        protected FormatterSimple initialValue() {
+            return new FormatterSimple();
         }
     };
 
-    private final FastDateFormat fastFormat = FastDateFormat.getInstance("HH:mm:ss.SSS");
-    private final CustomTimeFormat customFormat = CustomTimeFormat.createIfSupported("HH:mm:ss.SSS");
-    private final CustomFormatReuseBuffer customFormatReuseBuffer = new CustomFormatReuseBuffer();
+    private final FastDateFormat fastDateFormat = FastDateFormat.getInstance("HH:mm:ss.SSS");
+    private final FixedDateFormat fixedDateFormat = FixedDateFormat.createIfSupported("HH:mm:ss.SSS");
+    private final FormatterFixedReuseBuffer formatFixedReuseBuffer = new FormatterFixedReuseBuffer();
     
-    private class CurrentTime {
+    private class CachedTimeFastFormat {
         private final long timestamp;
         private final String formatted;
 
-        public CurrentTime(final long timestamp) {
+        public CachedTimeFastFormat(final long timestamp) {
             this.timestamp = timestamp;
-            this.formatted = fastFormat.format(timestamp);
+            this.formatted = fastDateFormat.format(timestamp);
         }
     }
 
-    private class CustomCurrentTime {
+    private class CachedTimeFixedFmt {
         private final long timestamp;
         private final String formatted;
 
-        public CustomCurrentTime(final long timestamp) {
+        public CachedTimeFixedFmt(final long timestamp) {
             this.timestamp = timestamp;
-            this.formatted = customFormat.format(timestamp);
+            this.formatted = fixedDateFormat.format(timestamp);
         }
     }
 
-    private class Formatter {
+    private class FormatterSimple {
         private final SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss.SSS");
         private long timestamp;
         private String formatted;
 
-        public Formatter() {
+        public FormatterSimple() {
             this.timestamp = 0;
         }
 
@@ -106,8 +106,8 @@ public class ThreadsafeDateFormatBenchmark {
         }
     }
 
-    private class CustomFormatReuseBuffer {
-        private final CustomTimeFormat customFormat = CustomTimeFormat.createIfSupported("HH:mm:ss.SSS");
+    private class FormatterFixedReuseBuffer {
+        private final FixedDateFormat customFormat = FixedDateFormat.createIfSupported("HH:mm:ss.SSS");
         private long timestamp;
         private String formatted;
         private final ThreadLocal<char[]> reusableBuffer = new ThreadLocal<char[]>() {
@@ -117,7 +117,7 @@ public class ThreadsafeDateFormatBenchmark {
             }
         };
 
-        public CustomFormatReuseBuffer() {
+        public FormatterFixedReuseBuffer() {
             this.timestamp = 0;
         }
 
@@ -135,8 +135,8 @@ public class ThreadsafeDateFormatBenchmark {
     private final long currentTimestamp = 0;
     private String cachedTime = null;
 
-    private final AtomicReference<CurrentTime> currentTime = new AtomicReference<>(new CurrentTime(System.currentTimeMillis()));
-    private final AtomicReference<CustomCurrentTime> customCurrentTime = new AtomicReference<>(new CustomCurrentTime(System.currentTimeMillis()));
+    private final AtomicReference<CachedTimeFastFormat> cachedTimeFastFmt = new AtomicReference<>(new CachedTimeFastFormat(System.nanoTime()));
+    private final AtomicReference<CachedTimeFixedFmt> cachedTimeFixedFmt = new AtomicReference<>(new CachedTimeFixedFmt(System.nanoTime()));
 
     public static void main(final String[] args) {
     }
@@ -151,7 +151,7 @@ public class ThreadsafeDateFormatBenchmark {
     @BenchmarkMode(Mode.SampleTime)
     @OutputTimeUnit(TimeUnit.NANOSECONDS)
     public String synchronizedSimpleDateFmt() {
-        final long timestamp = System.currentTimeMillis();
+        final long timestamp = System.nanoTime();
         synchronized (simpleDateFormat) {
             if (timestamp != currentTimestamp) {
                 cachedTime = simpleDateFormat.format(date);
@@ -164,52 +164,52 @@ public class ThreadsafeDateFormatBenchmark {
     @BenchmarkMode(Mode.SampleTime)
     @OutputTimeUnit(TimeUnit.NANOSECONDS)
     public String threadLocalSimpleDateFmt() {
-        final long timestamp = System.currentTimeMillis();
-        return threadLocal.get().format(timestamp);
+        final long timestamp = System.nanoTime();
+        return threadLocalSDFormat.get().format(timestamp);
     }
 
     @Benchmark
     @BenchmarkMode(Mode.SampleTime)
     @OutputTimeUnit(TimeUnit.NANOSECONDS)
     public String cachedThrdLocalSimpleDateFmt() {
-        final long timestamp = System.currentTimeMillis();
-        return localFormat.get().format(timestamp);
+        final long timestamp = System.nanoTime();
+        return threadLocalCachedSDFormat.get().format(timestamp);
     }
 
     @Benchmark
     @BenchmarkMode(Mode.SampleTime)
     @OutputTimeUnit(TimeUnit.NANOSECONDS)
     public String cachedThrdLocalCustomFormat() {
-        final long timestamp = System.currentTimeMillis();
-        return customFormatReuseBuffer.format(timestamp);
+        final long timestamp = System.nanoTime();
+        return formatFixedReuseBuffer.format(timestamp);
     }
 
     @Benchmark
     @BenchmarkMode(Mode.SampleTime)
     @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public String fastFormat() {
-        return fastFormat.format(System.currentTimeMillis());
+    public String fastDateFormat() {
+        return fastDateFormat.format(System.nanoTime());
     }
 
     @Benchmark
     @BenchmarkMode(Mode.SampleTime)
     @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public String customFormat() {
-        return customFormat.format(System.currentTimeMillis());
+    public String fixedDateFormat() {
+        return fixedDateFormat.format(System.nanoTime());
     }
 
     @Benchmark
     @BenchmarkMode(Mode.SampleTime)
     @OutputTimeUnit(TimeUnit.NANOSECONDS)
     public String atomicFastFormat() {
-        final long timestamp = System.currentTimeMillis();
-        final CurrentTime current = currentTime.get();
+        final long timestamp = System.nanoTime();
+        final CachedTimeFastFormat current = cachedTimeFastFmt.get();
         if (timestamp != current.timestamp) {
-            final CurrentTime newTime = new CurrentTime(timestamp);
-            if (currentTime.compareAndSet(current, newTime)) {
+            final CachedTimeFastFormat newTime = new CachedTimeFastFormat(timestamp);
+            if (cachedTimeFastFmt.compareAndSet(current, newTime)) {
                 return newTime.formatted;
             } else {
-                return currentTime.get().formatted;
+                return cachedTimeFastFmt.get().formatted;
             }
 
         }
@@ -219,15 +219,15 @@ public class ThreadsafeDateFormatBenchmark {
     @Benchmark
     @BenchmarkMode(Mode.SampleTime)
     @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public String atomicCustomFormat() {
-        final long timestamp = System.currentTimeMillis();
-        final CustomCurrentTime current = customCurrentTime.get();
+    public String atomicFixedFormat() {
+        final long timestamp = System.nanoTime();
+        final CachedTimeFixedFmt current = cachedTimeFixedFmt.get();
         if (timestamp != current.timestamp) {
-            final CustomCurrentTime newTime = new CustomCurrentTime(timestamp);
-            if (customCurrentTime.compareAndSet(current, newTime)) {
+            final CachedTimeFixedFmt newTime = new CachedTimeFixedFmt(timestamp);
+            if (cachedTimeFixedFmt.compareAndSet(current, newTime)) {
                 return newTime.formatted;
             } else {
-                return customCurrentTime.get().formatted;
+                return cachedTimeFixedFmt.get().formatted;
             }
 
         }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d8935c8a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/TimeFormatBenchmark.java
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/TimeFormatBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/TimeFormatBenchmark.java
index 1d6f4ff..74e76f7 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/TimeFormatBenchmark.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/TimeFormatBenchmark.java
@@ -23,7 +23,7 @@ import java.util.Calendar;
 import java.util.Date;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.logging.log4j.core.util.datetime.CustomTimeFormat;
+import org.apache.logging.log4j.core.util.datetime.FixedDateFormat;
 import org.apache.logging.log4j.core.util.datetime.FastDateFormat;
 import org.openjdk.jmh.annotations.Benchmark;
 import org.openjdk.jmh.annotations.BenchmarkMode;
@@ -56,7 +56,7 @@ public class TimeFormatBenchmark {
         }
     };
     FastDateFormat fastDateFormat = FastDateFormat.getInstance("HH:mm:ss.SSS");
-    CustomTimeFormat customTimeFormat = CustomTimeFormat.createIfSupported(new String[]{"ABSOLUTE"});
+    FixedDateFormat fixedDateFormat = FixedDateFormat.createIfSupported(new String[]{"ABSOLUTE"});
     volatile long midnightToday = 0;
     volatile long midnightTomorrow = 0;
 
@@ -87,8 +87,8 @@ public class TimeFormatBenchmark {
     }
 
     public static void main(final String[] args) {
-        System.out.println(new TimeFormatBenchmark().customBitFiddlingReuseCharArray(new BufferState()));
-        System.out.println(new TimeFormatBenchmark().customFormatReuseStringBuilder(new BufferState()));
+        System.out.println(new TimeFormatBenchmark().fixedBitFiddlingReuseCharArray(new BufferState()));
+        System.out.println(new TimeFormatBenchmark().fixedFormatReuseStringBuilder(new BufferState()));
     }
 
     @Benchmark
@@ -117,7 +117,7 @@ public class TimeFormatBenchmark {
     @Benchmark
     @BenchmarkMode(Mode.SampleTime)
     @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public String customBitFiddlingReuseCharArray(final BufferState state) {
+    public String fixedBitFiddlingReuseCharArray(final BufferState state) {
         final int len = formatCharArrayBitFiddling(System.currentTimeMillis(), state.charArray, 0);
         return new String(state.charArray, 0, len);
     }
@@ -125,22 +125,22 @@ public class TimeFormatBenchmark {
     @Benchmark
     @BenchmarkMode(Mode.SampleTime)
     @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public String customTimeFormatCreateNewCharArray(final BufferState state) {
-        return customTimeFormat.format(System.currentTimeMillis());
+    public String fixedDateFormatCreateNewCharArray(final BufferState state) {
+        return fixedDateFormat.format(System.currentTimeMillis());
     }
 
     @Benchmark
     @BenchmarkMode(Mode.SampleTime)
     @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public String customTimeFormatReuseCharArray(final BufferState state) {
-        final int len = customTimeFormat.format(System.currentTimeMillis(), state.charArray, 0);
+    public String fixedDateFormatReuseCharArray(final BufferState state) {
+        final int len = fixedDateFormat.format(System.currentTimeMillis(), state.charArray, 0);
         return new String(state.charArray, 0, len);
     }
 
     @Benchmark
     @BenchmarkMode(Mode.SampleTime)
     @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public String customFormatReuseStringBuilder(final BufferState state) {
+    public String fixedFormatReuseStringBuilder(final BufferState state) {
         state.stringBuilder.setLength(0);
         formatStringBuilder(System.currentTimeMillis(), state.stringBuilder);
         return new String(state.stringBuilder);