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/21 21:17:19 UTC

logging-log4j2 git commit: Renamed SimpleDateFormatBenchmark to ThreadsafeDateFormatBenchmark and added CustomTimeFormat variants

Repository: logging-log4j2
Updated Branches:
  refs/heads/master 24e89e7cd -> e0d138bd3


Renamed SimpleDateFormatBenchmark to ThreadsafeDateFormatBenchmark and
added CustomTimeFormat variants

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

Branch: refs/heads/master
Commit: e0d138bd3681d787b5896f5211bf566bedf5e049
Parents: 24e89e7
Author: rpopma <rp...@apache.org>
Authored: Sat Aug 22 04:17:29 2015 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sat Aug 22 04:17:29 2015 +0900

----------------------------------------------------------------------
 .../core/util/datetime/CustomTimeFormat.java    |   2 +-
 .../util/datetime/CustomTimeFormatTest.java     |   2 +-
 .../perf/jmh/SimpleDateFormatBenchmark.java     | 165 -------------
 .../perf/jmh/ThreadsafeDateFormatBenchmark.java | 236 +++++++++++++++++++
 4 files changed, 238 insertions(+), 167 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e0d138bd/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
index 07b730f..da90b44 100644
--- 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
@@ -127,7 +127,7 @@ public class CustomTimeFormat {
         }
     }
 
-    public static CustomTimeFormat createIfSupported(final String[] options) {
+    public static CustomTimeFormat createIfSupported(final String... options) {
         if (options == null || options.length == 0 || options.length > 1) {
             return null; // time zone not supported
         }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e0d138bd/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
index c277c5b..be674c1 100644
--- 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
@@ -99,7 +99,7 @@ public class CustomTimeFormatTest {
 
     @Test
     public void testCreateIfSupported_nullIfOptionsArrayNull() {
-        assertNull("null", CustomTimeFormat.createIfSupported(null));
+        assertNull("null", CustomTimeFormat.createIfSupported((String[]) null));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e0d138bd/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/SimpleDateFormatBenchmark.java
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/SimpleDateFormatBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/SimpleDateFormatBenchmark.java
deleted file mode 100644
index f1e7fde..0000000
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/SimpleDateFormatBenchmark.java
+++ /dev/null
@@ -1,165 +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.perf.jmh;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.logging.log4j.core.util.datetime.FastDateFormat;
-import org.openjdk.jmh.annotations.Benchmark;
-import org.openjdk.jmh.annotations.BenchmarkMode;
-import org.openjdk.jmh.annotations.Mode;
-import org.openjdk.jmh.annotations.OutputTimeUnit;
-import org.openjdk.jmh.annotations.Scope;
-import org.openjdk.jmh.annotations.State;
-
-/**
- * Tests performance of various ways to use SimpleDateFormat in a thread-safe manner.
- */
-// ============================== HOW TO RUN THIS TEST: ====================================
-//
-// single thread:
-// java -jar log4j-perf/target/benchmarks.jar ".*SimpleDateFormat.*" -f 1 -wi 5 -i 5
-//
-// multiple threads (for example, 4 threads):
-// java -jar log4j-perf/target/benchmarks.jar ".*SimpleDateFormat.*" -f 1 -wi 5 -i 5 -t 4 -si true
-//
-// Usage help:
-// java -jar log4j-perf/target/benchmarks.jar -help
-//
-@State(Scope.Benchmark)
-public class SimpleDateFormatBenchmark {
-
-    private final Date date = new Date();
-    private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
-    private final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>() {
-        @Override
-        protected SimpleDateFormat initialValue() {
-            return new SimpleDateFormat("HH:mm:ss.SSS");
-        }
-    };
-
-    private final ThreadLocal<Formatter> localFormat = new ThreadLocal<Formatter>() {
-        @Override
-        protected Formatter initialValue() {
-            return new Formatter();
-        }
-    };
-
-    private final FastDateFormat fastFormat = FastDateFormat.getInstance("HH:mm:ss.SSS");
-
-    private class CurrentTime {
-        private final long timestamp;
-        private final String formatted;
-
-        public CurrentTime(final long timestamp) {
-            this.timestamp = timestamp;
-            this.formatted = fastFormat.format(timestamp);
-        }
-    }
-
-    private class Formatter {
-        private final SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss.SSS");
-        private long timestamp;
-        private String formatted;
-
-        public Formatter() {
-            this.timestamp = 0;
-        }
-
-        public String format(final long timestamp) {
-            if (timestamp != this.timestamp) {
-                this.timestamp = timestamp;
-                formatted = format.format(timestamp);
-            }
-            return formatted;
-        }
-
-    }
-
-    private final long currentTimestamp = 0;
-    private String cachedTime = null;
-
-    private final AtomicReference<CurrentTime> currentTime = new AtomicReference<>(new CurrentTime(System.currentTimeMillis()));
-
-    public static void main(final String[] args) {
-    }
-
-    @Benchmark
-    @BenchmarkMode(Mode.SampleTime)
-    @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public void baseline() {
-    }
-
-    @Benchmark
-    @BenchmarkMode(Mode.SampleTime)
-    @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public String synchronizedFormat() {
-        final long timestamp = System.currentTimeMillis();
-        synchronized (simpleDateFormat) {
-            if (timestamp != currentTimestamp) {
-                cachedTime = simpleDateFormat.format(date);
-            }
-            return cachedTime;
-        }
-    }
-
-    @Benchmark
-    @BenchmarkMode(Mode.SampleTime)
-    @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public String threadLocalFormat() {
-        final long timestamp = System.currentTimeMillis();
-        return threadLocal.get().format(timestamp);
-    }
-
-
-    @Benchmark
-    @BenchmarkMode(Mode.SampleTime)
-    @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public String cachedFormat() {
-        final long timestamp = System.currentTimeMillis();
-        return localFormat.get().format(timestamp);
-    }
-
-    @Benchmark
-    @BenchmarkMode(Mode.SampleTime)
-    @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public String fastFormat() {
-        return fastFormat.format(System.currentTimeMillis());
-    }
-
-    @Benchmark
-    @BenchmarkMode(Mode.SampleTime)
-    @OutputTimeUnit(TimeUnit.NANOSECONDS)
-    public String atomicFormat() {
-        final long timestamp = System.currentTimeMillis();
-        final CurrentTime current = currentTime.get();
-        if (timestamp != current.timestamp) {
-            final CurrentTime newTime = new CurrentTime(timestamp);
-            if (currentTime.compareAndSet(current, newTime)) {
-                return newTime.formatted;
-            } else {
-                return currentTime.get().formatted;
-            }
-
-        }
-        return current.formatted;
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e0d138bd/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
new file mode 100644
index 0000000..ff06520
--- /dev/null
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/ThreadsafeDateFormatBenchmark.java
@@ -0,0 +1,236 @@
+/*
+ * 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.perf.jmh;
+
+import java.text.SimpleDateFormat;
+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.FastDateFormat;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+
+/**
+ * Tests performance of various DateFormatters in a thread-safe manner.
+ */
+// ============================== HOW TO RUN THIS TEST: ====================================
+//
+// single thread:
+// java -jar log4j-perf/target/benchmarks.jar ".*ThreadsafeDateFormat.*" -f 1 -wi 5 -i 10
+//
+// multiple threads (for example, 4 threads):
+// java -jar log4j-perf/target/benchmarks.jar ".*ThreadsafeDateFormat.*" -f 1 -wi 5 -i 10 -t 4 -si true
+//
+// Usage help:
+// java -jar log4j-perf/target/benchmarks.jar -help
+//
+@State(Scope.Benchmark)
+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>() {
+        @Override
+        protected SimpleDateFormat initialValue() {
+            return new SimpleDateFormat("HH:mm:ss.SSS");
+        }
+    };
+
+    private final ThreadLocal<Formatter> localFormat = new ThreadLocal<Formatter>() {
+        @Override
+        protected Formatter initialValue() {
+            return new Formatter();
+        }
+    };
+
+    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 class CurrentTime {
+        private final long timestamp;
+        private final String formatted;
+
+        public CurrentTime(final long timestamp) {
+            this.timestamp = timestamp;
+            this.formatted = fastFormat.format(timestamp);
+        }
+    }
+
+    private class CustomCurrentTime {
+        private final long timestamp;
+        private final String formatted;
+
+        public CustomCurrentTime(final long timestamp) {
+            this.timestamp = timestamp;
+            this.formatted = customFormat.format(timestamp);
+        }
+    }
+
+    private class Formatter {
+        private final SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss.SSS");
+        private long timestamp;
+        private String formatted;
+
+        public Formatter() {
+            this.timestamp = 0;
+        }
+
+        public String format(final long timestamp) {
+            if (timestamp != this.timestamp) {
+                this.timestamp = timestamp;
+                formatted = format.format(timestamp);
+            }
+            return formatted;
+        }
+    }
+
+    private class CustomFormatReuseBuffer {
+        private final CustomTimeFormat customFormat = CustomTimeFormat.createIfSupported("HH:mm:ss.SSS");
+        private long timestamp;
+        private String formatted;
+        private final ThreadLocal<char[]> reusableBuffer = new ThreadLocal<char[]>() {
+            @Override
+            protected char[] initialValue() {
+                return new char[255];
+            }
+        };
+
+        public CustomFormatReuseBuffer() {
+            this.timestamp = 0;
+        }
+
+        public String format(final long timestamp) {
+            if (timestamp != this.timestamp) {
+                this.timestamp = timestamp;
+                char[] buffer = reusableBuffer.get();
+                int len = customFormat.format(timestamp, buffer, 0);
+                formatted = new String(buffer, 0, len);
+            }
+            return formatted;
+        }
+    }
+
+    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()));
+
+    public static void main(final String[] args) {
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.SampleTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public void baseline() {
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.SampleTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public String synchronizedSimpleDateFmt() {
+        final long timestamp = System.currentTimeMillis();
+        synchronized (simpleDateFormat) {
+            if (timestamp != currentTimestamp) {
+                cachedTime = simpleDateFormat.format(date);
+            }
+            return cachedTime;
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.SampleTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public String threadLocalSimpleDateFmt() {
+        final long timestamp = System.currentTimeMillis();
+        return threadLocal.get().format(timestamp);
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.SampleTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public String cachedThrdLocalSimpleDateFmt() {
+        final long timestamp = System.currentTimeMillis();
+        return localFormat.get().format(timestamp);
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.SampleTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public String cachedThrdLocalCustomFormat() {
+        final long timestamp = System.currentTimeMillis();
+        return customFormatReuseBuffer.format(timestamp);
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.SampleTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public String fastFormat() {
+        return fastFormat.format(System.currentTimeMillis());
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.SampleTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public String customFormat() {
+        return customFormat.format(System.currentTimeMillis());
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.SampleTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public String atomicFastFormat() {
+        final long timestamp = System.currentTimeMillis();
+        final CurrentTime current = currentTime.get();
+        if (timestamp != current.timestamp) {
+            final CurrentTime newTime = new CurrentTime(timestamp);
+            if (currentTime.compareAndSet(current, newTime)) {
+                return newTime.formatted;
+            } else {
+                return currentTime.get().formatted;
+            }
+
+        }
+        return current.formatted;
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.SampleTime)
+    @OutputTimeUnit(TimeUnit.NANOSECONDS)
+    public String atomicCustomFormat() {
+        final long timestamp = System.currentTimeMillis();
+        final CustomCurrentTime current = customCurrentTime.get();
+        if (timestamp != current.timestamp) {
+            final CustomCurrentTime newTime = new CustomCurrentTime(timestamp);
+            if (customCurrentTime.compareAndSet(current, newTime)) {
+                return newTime.formatted;
+            } else {
+                return customCurrentTime.get().formatted;
+            }
+
+        }
+        return current.formatted;
+    }
+}