On Mon, 1 Nov 2021 22:18:52 GMT, Stephen Colebourne <scolebou...@openjdk.org> wrote:
>> Prompted by a request from Volkan Yazıcı I took a look at why the java.time >> formatters are less efficient for some common patterns than custom >> formatters in apache-commons and log4j. This patch reduces the 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 > > src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java > line 3269: > >> 3267: return false; >> 3268: } >> 3269: int val = value.intValue(); // NANO_OF_SECOND must fit in >> an int and can't be negative > > Unfortunately, this is not a valid assumption, and it affects the logic of > the optimization more generally (methods where non-negative is assumed). > > Basically, NANO_OF_SECOND (and all other fields in the formatter) can have > any `long` value. Despite immediate appearances, the value is not limited to > 0 to 999,999,999. This is because you are allowed to create an implementation > of `Temporal` that returns values outside that range. No such class exists in > the JDK, but such a class would be perfectly legal. As a related example, it > would be perfectly value to write a time class that ran from 03:00 to 26:59 > each day, thus HOUROF_DAY cannot be assumed by the formatter to be between 0 > and 23. The commentary on this line could probably be improved, but this is in a private printer-parser that will only be used for NANO_OF_SECOND and not any arbitrary `Temporal` (see line 704), thus I fail to see how this assumption can fail (since NANO_OF_SECOND specifies a value range from 0 to 999,999,999). I considered writing a more generic integral-fraction printer parser that would optimize for any value-range that fits in an int, but seeing how NANO_OF_SECOND is likely the only one used in practice and with a high demand for better efficiency I opted to specialize for it more directly. ------------- PR: https://git.openjdk.java.net/jdk/pull/6188