From bd9adbb637a8a4aa5eb61c6fde2c576d0ab3c4fa Mon Sep 17 00:00:00 2001 From: Chas Honton Date: Sat, 16 Jul 2016 19:24:55 -0700 Subject: [PATCH] LANG-1248: FastDatePrinter Memory allocation regression closes #169 --- src/changes/changes.xml | 3 +- .../commons/lang3/time/FastDatePrinter.java | 75 +++++++++++++++---- 2 files changed, 62 insertions(+), 16 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 888757230..96487a2c6 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,7 +46,8 @@ The type attribute can be add,update,fix,remove. - FastDatePrinter generates extra Date objects + FastDatePrinter Memory allocation regression + FastDatePrinter generates extra Date objects Fix precision loss on NumberUtils.createNumber(String) HashCodeBuilder.append(Object,Object) is too big to be inlined, which prevents whole builder to be scalarized Add a circuit breaker implementation 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 ff1fbac0e..13a78992e 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 - // pad with zeros - while(digit 0; --i) { + buffer.append('0'); + } - // reverse - while(--digit>=0) { - buffer.append(work[digit]); + 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]); + } } }