You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2020/03/03 14:36:40 UTC

[tomcat] branch master updated: BZ 64190 Add 'proper' ms support to OneLineFormatter.

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

markt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/master by this push:
     new 4ad0a71  BZ 64190 Add 'proper' ms support to OneLineFormatter.
4ad0a71 is described below

commit 4ad0a71bc11de50e0fe23fc38e6e67f134aa0589
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Mar 3 14:36:08 2020 +0000

    BZ 64190 Add 'proper' ms support to OneLineFormatter.
    
    S SS or SSS can now be used (once) anywhere in the format String.
    Format strings without S SS or SSS are now ~30% faster
    The current default (effectively "dd-MMM-yyyy HH:mm:ss.SSS") is within
    less than 1% of the old implementation.
    Using S SS or SSS anywhere but the very end doubles the time taken to
    generate the timestamp.
---
 java/org/apache/juli/OneLineFormatter.java         | 77 +++++++++++++++++++---
 .../TestOneLineFormatterMillisPerformance.java     | 70 ++++++++++++++++++++
 webapps/docs/changelog.xml                         |  5 ++
 3 files changed, 142 insertions(+), 10 deletions(-)

diff --git a/java/org/apache/juli/OneLineFormatter.java b/java/org/apache/juli/OneLineFormatter.java
index 75845cf..fad37b0 100644
--- a/java/org/apache/juli/OneLineFormatter.java
+++ b/java/org/apache/juli/OneLineFormatter.java
@@ -51,7 +51,7 @@ public class OneLineFormatter extends Formatter {
     };
 
     /* Timestamp format */
-    private static final String DEFAULT_TIME_FORMAT = "dd-MMM-yyyy HH:mm:ss";
+    private static final String DEFAULT_TIME_FORMAT = "dd-MMM-yyyy HH:mm:ss.SSS";
 
     /**
      * The size of our global date format cache
@@ -68,6 +68,8 @@ public class OneLineFormatter extends Formatter {
      */
     private ThreadLocal<DateFormatCache> localDateCache;
 
+    private volatile MillisHandling millisHandling = MillisHandling.APPEND;
+
 
     public OneLineFormatter() {
         String timeFormat = LogManager.getLogManager().getProperty(
@@ -86,12 +88,31 @@ public class OneLineFormatter extends Formatter {
      *                   {@link java.text.SimpleDateFormat} syntax
      */
     public void setTimeFormat(final String timeFormat) {
+        final String cachedTimeFormat;
+
+        if (timeFormat.endsWith(".SSS")) {
+            cachedTimeFormat = timeFormat.substring(0,  timeFormat.length() - 4);
+            millisHandling = MillisHandling.APPEND;
+        } else if (timeFormat.contains("SSS")) {
+            millisHandling = MillisHandling.REPLACE_SSS;
+            cachedTimeFormat = timeFormat;
+        } else if (timeFormat.contains("SS")) {
+            millisHandling = MillisHandling.REPLACE_SS;
+            cachedTimeFormat = timeFormat;
+        } else if (timeFormat.contains("S")) {
+            millisHandling = MillisHandling.REPLACE_S;
+            cachedTimeFormat = timeFormat;
+        } else {
+            millisHandling = MillisHandling.NONE;
+            cachedTimeFormat = timeFormat;
+        }
+
         final DateFormatCache globalDateCache =
-                new DateFormatCache(globalCacheSize, timeFormat, null);
+                new DateFormatCache(globalCacheSize, cachedTimeFormat, null);
         localDateCache = new ThreadLocal<DateFormatCache>() {
             @Override
             protected DateFormatCache initialValue() {
-                return new DateFormatCache(localCacheSize, timeFormat, globalDateCache);
+                return new DateFormatCache(localCacheSize, cachedTimeFormat, globalDateCache);
             }
         };
     }
@@ -156,18 +177,45 @@ public class OneLineFormatter extends Formatter {
     }
 
     protected void addTimestamp(StringBuilder buf, long timestamp) {
-        buf.append(localDateCache.get().getFormat(timestamp));
-        long frac = timestamp % 1000;
-        buf.append('.');
-        if (frac < 100) {
-            if (frac < 10) {
+        String cachedTimeStamp = localDateCache.get().getFormat(timestamp);
+        if (millisHandling == MillisHandling.NONE) {
+            buf.append(cachedTimeStamp);
+        } else if (millisHandling == MillisHandling.APPEND) {
+            buf.append(cachedTimeStamp);
+            long frac = timestamp % 1000;
+            buf.append('.');
+            if (frac < 100) {
+                if (frac < 10) {
+                    buf.append('0');
+                    buf.append('0');
+                } else {
+                    buf.append('0');
+                }
+            }
+            buf.append(frac);
+        } else {
+            // Some version of replace
+            long frac = timestamp % 1000;
+            // Formatted string may vary in length so the insert point may vary
+            int insertStart = cachedTimeStamp.indexOf('#');
+            buf.append(cachedTimeStamp.subSequence(0, insertStart));
+            if (frac < 100 && millisHandling == MillisHandling.REPLACE_SSS) {
                 buf.append('0');
+                if (frac < 10) {
+                    buf.append('0');
+                }
+            } else if (frac < 10 && millisHandling == MillisHandling.REPLACE_SS) {
                 buf.append('0');
+            }
+            buf.append(frac);
+            if (millisHandling == MillisHandling.REPLACE_SSS) {
+                buf.append(cachedTimeStamp.substring(insertStart + 3));
+            } else if (millisHandling == MillisHandling.REPLACE_SS) {
+                buf.append(cachedTimeStamp.substring(insertStart + 2));
             } else {
-                buf.append('0');
+                buf.append(cachedTimeStamp.substring(insertStart + 1));
             }
         }
-        buf.append(frac);
     }
 
 
@@ -250,4 +298,13 @@ public class OneLineFormatter extends Formatter {
             super.println(x);
         }
     }
+
+
+    private static enum MillisHandling {
+        NONE,
+        APPEND,
+        REPLACE_S,
+        REPLACE_SS,
+        REPLACE_SSS,
+    }
 }
diff --git a/test/org/apache/juli/TestOneLineFormatterMillisPerformance.java b/test/org/apache/juli/TestOneLineFormatterMillisPerformance.java
new file mode 100644
index 0000000..b7c0cab
--- /dev/null
+++ b/test/org/apache/juli/TestOneLineFormatterMillisPerformance.java
@@ -0,0 +1,70 @@
+/*
+ * 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.juli;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+
+@RunWith(Parameterized.class)
+public class TestOneLineFormatterMillisPerformance {
+
+    @Parameterized.Parameters(name = "{index}: format[{0}]")
+    public static Collection<Object[]> parameters() {
+
+        List<Object[]> parameterSets = new ArrayList<>();
+
+        parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss.SSS" });
+        parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss.SS" });
+        parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss.S" });
+        parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss" });
+        parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss XXX" });
+        parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss.SSSXXX" });
+        parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss.SSXXX" });
+        parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss.SXXX" });
+        parameterSets.add(new String[] { "SSS dd-MMM-yyyy HH:mm:ss" });
+        parameterSets.add(new String[] { "SS dd-MMM-yyyy HH:mm:ss" });
+        parameterSets.add(new String[] { "S dd-MMM-yyyy HH:mm:ss" });
+
+        return parameterSets;
+    }
+
+
+    @Parameter(0)
+    public String timestampFormat;
+
+    @Test
+    public void testMillisHandling() {
+        OneLineFormatter olf = new OneLineFormatter();
+        olf.setTimeFormat(timestampFormat);
+
+        long timeStamp = System.currentTimeMillis();
+        StringBuilder buf = new StringBuilder(64);
+
+        long start = System.nanoTime();
+        for (int i = 0; i < 10000000; i++) {
+            buf.setLength(0);
+            olf.addTimestamp(buf, timeStamp);
+        }
+        System.out.println("Format: [" + timestampFormat + "], Output: [" + buf + "], Duration: [" + (System.nanoTime() - start) + "] ns");
+    }
+}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index cf486e2..38a525b 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -160,6 +160,11 @@
         Expand the coverage of the French translations provided with Apache
         Tomcat. (remm)
       </add>
+      <add>
+        <bug>64190</bug>: Add support for specifing milliseconds (using
+        <code>S</code>, <code>SS</code> or <code>SSS</code>) in the timestamp
+        used by JULI&apos;s <code>OneLineFormatter</code>. (markt)
+      </add>
     </changelog>
   </subsection>
 </section>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: [tomcat] branch master updated: BZ 64190 Add 'proper' ms support to OneLineFormatter.

Posted by Mark Thomas <ma...@apache.org>.
On 04/03/2020 17:27, Christopher Schultz wrote:
> Mark,
> 
> On 3/3/20 09:36, markt@apache.org wrote:
>> This is an automated email from the ASF dual-hosted git
>> repository.
> 
>> markt pushed a commit to branch master in repository
>> https://gitbox.apache.org/repos/asf/tomcat.git
> 
> 
>> The following commit(s) were added to refs/heads/master by this
>> push: new 4ad0a71  BZ 64190 Add 'proper' ms support to
>> OneLineFormatter. 4ad0a71 is described below
> 
>> commit 4ad0a71bc11de50e0fe23fc38e6e67f134aa0589 Author: Mark Thomas
>> <ma...@apache.org> AuthorDate: Tue Mar 3 14:36:08 2020 +0000
> 
>> BZ 64190 Add 'proper' ms support to OneLineFormatter.

<snip/>

>> int insertStart = cachedTimeStamp.indexOf('#');
> 
> Should the literal '#' be the DateFormatCache.msecPattern constant
> instead? It's unlikely to change, but it's slightly less "magic
> character"-ish if you reference the constant.

Yes, that would be better.

Mark

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: [tomcat] branch master updated: BZ 64190 Add 'proper' ms support to OneLineFormatter.

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Mark,

On 3/3/20 09:36, markt@apache.org wrote:
> This is an automated email from the ASF dual-hosted git
> repository.
>
> markt pushed a commit to branch master in repository
> https://gitbox.apache.org/repos/asf/tomcat.git
>
>
> The following commit(s) were added to refs/heads/master by this
> push: new 4ad0a71  BZ 64190 Add 'proper' ms support to
> OneLineFormatter. 4ad0a71 is described below
>
> commit 4ad0a71bc11de50e0fe23fc38e6e67f134aa0589 Author: Mark Thomas
> <ma...@apache.org> AuthorDate: Tue Mar 3 14:36:08 2020 +0000
>
> BZ 64190 Add 'proper' ms support to OneLineFormatter.
>
> S SS or SSS can now be used (once) anywhere in the format String.
> Format strings without S SS or SSS are now ~30% faster The current
> default (effectively "dd-MMM-yyyy HH:mm:ss.SSS") is within less
> than 1% of the old implementation. Using S SS or SSS anywhere but
> the very end doubles the time taken to generate the timestamp. ---
> java/org/apache/juli/OneLineFormatter.java         | 77
> +++++++++++++++++++---
> .../TestOneLineFormatterMillisPerformance.java     | 70
> ++++++++++++++++++++ webapps/docs/changelog.xml
> |  5 ++ 3 files changed, 142 insertions(+), 10 deletions(-)
>
> diff --git a/java/org/apache/juli/OneLineFormatter.java
> b/java/org/apache/juli/OneLineFormatter.java index 75845cf..fad37b0
> 100644 --- a/java/org/apache/juli/OneLineFormatter.java +++
> b/java/org/apache/juli/OneLineFormatter.java @@ -51,7 +51,7 @@
> public class OneLineFormatter extends Formatter { };
>
> /* Timestamp format */ -    private static final String
> DEFAULT_TIME_FORMAT = "dd-MMM-yyyy HH:mm:ss"; +    private static
> final String DEFAULT_TIME_FORMAT = "dd-MMM-yyyy HH:mm:ss.SSS"; /**
> * The size of our global date format cache @@ -68,6 +68,8 @@ public
> class OneLineFormatter extends Formatter { */ private
> ThreadLocal<DateFormatCache> localDateCache;
>
> +    private volatile MillisHandling millisHandling =
> MillisHandling.APPEND; +
>
> public OneLineFormatter() { String timeFormat =
> LogManager.getLogManager().getProperty( @@ -86,12 +88,31 @@ public
> class OneLineFormatter extends Formatter { *
> {@link java.text.SimpleDateFormat} syntax */ public void
> setTimeFormat(final String timeFormat) { +        final String
> cachedTimeFormat; + +        if (timeFormat.endsWith(".SSS")) { +
> cachedTimeFormat = timeFormat.substring(0,  timeFormat.length() -
> 4); +            millisHandling = MillisHandling.APPEND; +        }
> else if (timeFormat.contains("SSS")) { +            millisHandling
> = MillisHandling.REPLACE_SSS; +            cachedTimeFormat =
> timeFormat; +        } else if (timeFormat.contains("SS")) { +
> millisHandling = MillisHandling.REPLACE_SS; +
> cachedTimeFormat = timeFormat; +        } else if
> (timeFormat.contains("S")) { +            millisHandling =
> MillisHandling.REPLACE_S; +            cachedTimeFormat =
> timeFormat; +        } else { +            millisHandling =
> MillisHandling.NONE; +            cachedTimeFormat = timeFormat; +
> } + final DateFormatCache globalDateCache = -                new
> DateFormatCache(globalCacheSize, timeFormat, null); +
> new DateFormatCache(globalCacheSize, cachedTimeFormat, null);
> localDateCache = new ThreadLocal<DateFormatCache>() { @Override
> protected DateFormatCache initialValue() { -                return
> new DateFormatCache(localCacheSize, timeFormat, globalDateCache); +
> return new DateFormatCache(localCacheSize, cachedTimeFormat,
> globalDateCache); } }; } @@ -156,18 +177,45 @@ public class
> OneLineFormatter extends Formatter { }
>
> protected void addTimestamp(StringBuilder buf, long timestamp) { -
> buf.append(localDateCache.get().getFormat(timestamp)); -
> long frac = timestamp % 1000; -        buf.append('.'); -        if
> (frac < 100) { -            if (frac < 10) { +        String
> cachedTimeStamp = localDateCache.get().getFormat(timestamp); +
> if (millisHandling == MillisHandling.NONE) { +
> buf.append(cachedTimeStamp); +        } else if (millisHandling ==
> MillisHandling.APPEND) { +            buf.append(cachedTimeStamp);
> +            long frac = timestamp % 1000; +
> buf.append('.'); +            if (frac < 100) { +                if
> (frac < 10) { +                    buf.append('0'); +
> buf.append('0'); +                } else { +
> buf.append('0'); +                } +            } +
> buf.append(frac); +        } else { +            // Some version of
> replace +            long frac = timestamp % 1000; +            //
> Formatted string may vary in length so the insert point may vary +
> int insertStart = cachedTimeStamp.indexOf('#');

Should the literal '#' be the DateFormatCache.msecPattern constant
instead? It's unlikely to change, but it's slightly less "magic
character"-ish if you reference the constant.

- -chris
-----BEGIN PGP SIGNATURE-----
Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/

iQIyBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl5f5RQACgkQHPApP6U8
pFh7tg/1GQOhbIMta5RdMwrNVuF6W+HuXDJsTWPg8gk+qkAHhy/aTtJT6MwTAhVs
wuJk12LkNLjP8PNDAyOXtkSZNQPH3Qjt3z+d5gtW0wSIqpluHKPwDCsbLv7ZobMr
mEUcwcH17h0IGNm2OC0qIU9i3MQ1NMf4/myuqMaW7nheukwYEQTxclNJCuJA98cM
ZK3sgsVTue07XZgtmaf7FO+PwQoQwbzkA5abht4Ia6mAgyeHEZpjXxWaV+Q+a/pf
pUhpYHGkEg2TfJqEaw56vt9lwnSR+yKFKb3p1NoItlSJGJRhh+/CH35bRPzUi6lF
b6W5A9Q5D8azOQ7u64d31nCUuxVZm3X4gktZaZl0wwGo6cn5xieAHUllIOSmMZ1A
17DR7vsVZBRgk/ieh9kW1jlW1FSzdCT0phkLNk1dYDmf8n16PHJTQw/MgX8Ziwzz
YIeA7LBFys8+frOHLwH5YMyqaZDMpciikDAOP+j5+NHOqMBzJ9nsNIkYbVk5riPu
XBSB927xpEkN1/ir1yIRyrCU+4ctCytQXEkzbEflL2pdXu2e9+sKewpEsaKlN8eN
9XHZe4cReSHbEvZYJNXoZH4EEo2TXYExcxDepMX5RKvGe5mQzxYT7aWnYnb/et0/
CtCihP25QArKO6661RG8YFpzlvBcdLhTQX/WouTNAyF4JiseFg==
=MhoK
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org