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 core-libs-dev
mailing list