<i18n dev> RFR: 8276220: Reduce excessive allocations in DateTimeFormatter

Claes Redestad redestad at openjdk.java.net
Mon Nov 1 15:27:37 UTC 2021


On Mon, 1 Nov 2021 13:04:20 GMT, Claes Redestad <redestad at openjdk.org> wrote:

> Prompted by a request from Volkan Yazıcı I took a look at why DataTimeFormatters are much less efficient for some common patterns than custom formatters in apache-commons and log4j. This patch address some of that gap, without having looked at the third party implementations. 
> 
> When printing times:
> - Avoid turning integral values into `String`s before appending them to the buffer 
> - Specialize `appendFraction` for `NANO_OF_SECOND` to avoid use of `BigDecimal`
> 
> This means a speed-up and reduction in allocations when formatting almost any date or time pattern, and especially so when including sub-second parts (`S-SSSSSSSSS`).
> 
> Much of the remaining overhead can be traced to the need to create a `DateTimePrintContext` and adjusting `Instant`s into a `ZonedDateTime` internally. We could likely also win performance by specializing some common patterns.
> 
> Testing: tier1-3

Microbenchmark numbers for the supplied `DateTimeFormatterBench`. 

Baseline:

Benchmark                               (pattern)   Mode  Cnt       Score       Error   Units
formatInstants                           HH:mm:ss  thrpt   15       6.558 ±     0.125  ops/ms
  ·gc.alloc.rate.norm                    HH:mm:ss  thrpt   15  192015.139 ±     0.352    B/op
formatInstants                       HH:mm:ss.SSS  thrpt   15       2.772 ±     0.036  ops/ms
  ·gc.alloc.rate.norm                HH:mm:ss.SSS  thrpt   15  696805.289 ± 11280.987    B/op
formatInstants              yyyy-MM-dd'T'HH:mm:ss  thrpt   15       4.025 ±     0.056  ops/ms
  ·gc.alloc.rate.norm       yyyy-MM-dd'T'HH:mm:ss  thrpt   15  264020.926 ±     0.555    B/op
formatInstants          yyyy-MM-dd'T'HH:mm:ss.SSS  thrpt   15       2.121 ±     0.026  ops/ms
  ·gc.alloc.rate.norm   yyyy-MM-dd'T'HH:mm:ss.SSS  thrpt   15  768811.221 ± 11281.118    B/op
formatZonedDateTime                      HH:mm:ss  thrpt   15       8.797 ±     0.254  ops/ms
  ·gc.alloc.rate.norm                    HH:mm:ss  thrpt   15   96007.787 ±     0.331    B/op
formatZonedDateTime                  HH:mm:ss.SSS  thrpt   15       3.109 ±     0.024  ops/ms
  ·gc.alloc.rate.norm                HH:mm:ss.SSS  thrpt   15  600798.055 ± 11280.992    B/op
formatZonedDateTime         yyyy-MM-dd'T'HH:mm:ss  thrpt   15       4.814 ±     0.037  ops/ms
  ·gc.alloc.rate.norm       yyyy-MM-dd'T'HH:mm:ss  thrpt   15  168013.636 ±     0.389    B/op
formatZonedDateTime     yyyy-MM-dd'T'HH:mm:ss.SSS  thrpt   15       2.299 ±     0.059  ops/ms
  ·gc.alloc.rate.norm   yyyy-MM-dd'T'HH:mm:ss.SSS  thrpt   15  680012.566 ± 11281.140    B/op


Patched:

Benchmark                               (pattern)   Mode  Cnt       Score      Error   Units
formatInstants                           HH:mm:ss  thrpt   15       7.721 ±    0.114  ops/ms
  ·gc.alloc.rate.norm                    HH:mm:ss  thrpt   15  120010.043 ±    0.934    B/op
formatInstants                       HH:mm:ss.SSS  thrpt   15       5.684 ±    0.083  ops/ms
  ·gc.alloc.rate.norm                HH:mm:ss.SSS  thrpt   15  120009.973 ±    0.608    B/op
formatInstants              yyyy-MM-dd'T'HH:mm:ss  thrpt   15       4.962 ±    0.058  ops/ms
  ·gc.alloc.rate.norm       yyyy-MM-dd'T'HH:mm:ss  thrpt   15  120010.027 ±    0.703    B/op
formatInstants          yyyy-MM-dd'T'HH:mm:ss.SSS  thrpt   15       3.889 ±    0.068  ops/ms
  ·gc.alloc.rate.norm   yyyy-MM-dd'T'HH:mm:ss.SSS  thrpt   15  120010.284 ±    1.003    B/op
formatZonedDateTime                      HH:mm:ss  thrpt   15      11.087 ±    0.404  ops/ms
  ·gc.alloc.rate.norm                    HH:mm:ss  thrpt   15   24002.072 ±    0.219    B/op
formatZonedDateTime                  HH:mm:ss.SSS  thrpt   15       7.325 ±    0.139  ops/ms
  ·gc.alloc.rate.norm                HH:mm:ss.SSS  thrpt   15   24002.080 ±    0.267    B/op
formatZonedDateTime         yyyy-MM-dd'T'HH:mm:ss  thrpt   15       6.127 ±    0.040  ops/ms
  ·gc.alloc.rate.norm       yyyy-MM-dd'T'HH:mm:ss  thrpt   15   24002.084 ±    0.459    B/op
formatZonedDateTime     yyyy-MM-dd'T'HH:mm:ss.SSS  thrpt   15       4.576 ±    0.049  ops/ms
  ·gc.alloc.rate.norm   yyyy-MM-dd'T'HH:mm:ss.SSS  thrpt   15   24002.102 ±    0.511    B/op


The most dramatic improvement is seen for `formatZonedDateTime` using the format `yyyy-MM-dd'T'HH:mm:ss.SSS`, which sees a 2x speed-up and almost 97% reduction in allocations. The same variant using `Instant`s see a 1.8x speed-up and almost 85% reduction in allocations.

-------------

PR: https://git.openjdk.java.net/jdk/pull/6188


More information about the i18n-dev mailing list