You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ch...@apache.org on 2016/07/17 02:28:29 UTC

[lang] LANG-1248: FastDatePrinter Memory allocation regression closes #169

Repository: commons-lang
Updated Branches:
  refs/heads/master 1d1883f0e -> bd9adbb63


LANG-1248: FastDatePrinter Memory allocation regression
closes #169


Project: http://git-wip-us.apache.org/repos/asf/commons-lang/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-lang/commit/bd9adbb6
Tree: http://git-wip-us.apache.org/repos/asf/commons-lang/tree/bd9adbb6
Diff: http://git-wip-us.apache.org/repos/asf/commons-lang/diff/bd9adbb6

Branch: refs/heads/master
Commit: bd9adbb637a8a4aa5eb61c6fde2c576d0ab3c4fa
Parents: 1d1883f
Author: Chas Honton <ch...@apache.org>
Authored: Sat Jul 16 19:24:55 2016 -0700
Committer: Chas Honton <ch...@apache.org>
Committed: Sat Jul 16 19:27:37 2016 -0700

----------------------------------------------------------------------
 src/changes/changes.xml                         |  3 +-
 .../commons/lang3/time/FastDatePrinter.java     | 75 ++++++++++++++++----
 2 files changed, 62 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-lang/blob/bd9adbb6/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 8887572..96487a2 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -46,7 +46,8 @@ The <action> type attribute can be add,update,fix,remove.
   <body>
 
   <release version="3.5" date="tba" description="tba">
-    <action issue="LANG-1247" type="update" dev="chas" due-to="Benoit Wiart">FastDatePrinter generates extra Date objects</action>
+    <action issue="LANG-1248" type="fix" dev="chas" due-to="Benoit Wiart">FastDatePrinter Memory allocation regression</action>
+    <action issue="LANG-1247" type="fix" dev="chas" due-to="Benoit Wiart">FastDatePrinter generates extra Date objects</action>
     <action issue="LANG-1018" type="fix" dev="pschumacher" due-to="Nick Manley">Fix precision loss on NumberUtils.createNumber(String)</action>
     <action issue="LANG-1229" type="update" dev="pschumacher" due-to="Ruslan Cheremin">HashCodeBuilder.append(Object,Object) is too big to be inlined, which prevents whole builder to be scalarized</action>
     <action issue="LANG-1085" type="add" dev="oheger" due-to="oheger / kinow">Add a circuit breaker implementation</action>

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/bd9adbb6/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java b/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java
index ff1fbac..13a7899 100644
--- a/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java
+++ b/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java
@@ -684,23 +684,68 @@ public class FastDatePrinter implements DatePrinter, Serializable {
      * @param value the value to append digits from.
      */
     private static void appendFullDigits(final Appendable buffer, int value, int minFieldWidth) throws IOException {
-        // build up decimal representation in reverse
-        char[] work = new char[MAX_DIGITS];
-        int digit = 0;
-        while(value!=0) {
-            work[digit++] = (char)(value % 10 + '0');
-            value = value / 10;
-        }
+        // specialized paths for 1 to 4 digits -> avoid the memory allocation from the temporary work array
+        // see LANG-1248
+        if (value < 10000) {
+            // less memory allocation path works for four digits or less
+
+            int nDigits = 4;
+            if (value < 1000) {
+                --nDigits;
+                if (value < 100) {
+                    --nDigits;
+                    if (value < 10) {
+                        --nDigits;
+                    }
+                }
+            }
+            // left zero pad
+            for (int i = minFieldWidth - nDigits; i > 0; --i) {
+                buffer.append('0');
+            }
 
-        // pad with zeros
-        while(digit<minFieldWidth) {
-            buffer.append('0');
-            --minFieldWidth;
-        }
+            switch (nDigits) {
+            case 4:
+                buffer.append((char) (value / 1000 + '0'));
+                value %= 1000;
+            case 3:
+                if (value >= 100) {
+                    buffer.append((char) (value / 100 + '0'));
+                    value %= 100;
+                } else {
+                    buffer.append('0');
+                }
+            case 2:
+                if (value >= 10) {
+                    buffer.append((char) (value / 10 + '0'));
+                    value %= 10;
+                } else {
+                    buffer.append('0');
+                }
+            case 1:
+                buffer.append((char) (value + '0'));
+            }
+        } else {
+            // more memory allocation path works for any digits
+
+            // build up decimal representation in reverse
+            char[] work = new char[MAX_DIGITS];
+            int digit = 0;
+            while (value != 0) {
+                work[digit++] = (char) (value % 10 + '0');
+                value = value / 10;
+            }
+
+            // pad with zeros
+            while (digit < minFieldWidth) {
+                buffer.append('0');
+                --minFieldWidth;
+            }
 
-        // reverse
-        while(--digit>=0) {
-            buffer.append(work[digit]);
+            // reverse
+            while (--digit >= 0) {
+                buffer.append(work[digit]);
+            }
         }
     }