<i18n dev> RFR: 8372460: Use EnumMap instead of HashMap for DateTimeFormatter parsing to improve performance

Shaojin Wen swen at openjdk.org
Tue Nov 25 06:32:37 UTC 2025


On Mon, 24 Nov 2025 08:02:35 GMT, Shaojin Wen <swen at openjdk.org> wrote:

> This PR optimizes the parsing performance of DateTimeFormatter by replacing HashMap with EnumMap in scenarios where the keys are exclusively ChronoField enum values.
> 
> When parsing date/time strings, DateTimeFormatter creates HashMaps to store intermediate parsed values. HashMap has more overhead for operations compared to specialized map implementations.
> 
> Since ChronoField is an enum and all keys in these maps are ChronoField instances, we can use EnumMap instead, which provides better performance for enum keys due to its optimized internal structure.
> 
> Parsing scenarios show improvements from 12% to 95%

# 1. Shell
We run the following Shell command

# master
git checkout b6495573e9dc5470df268b63f8e7a93f38406cd2
make test TEST="micro:java.time.format.DateTimeFormatterParse"

# this pr
git checkout d8742d7514abfe0e36f105fa7310fdb1755ae546
make test TEST="micro:java.time.format.DateTimeFormatterParse"



# 2. Raw Benchmark Data

Performance data running on a MacBook M1 Pro:


# b649557 (master)
Benchmark                                           Mode  Cnt     Score     Error   Units
DateTimeFormatterParse.parseInstant                thrpt   15  2066.130 ± 126.134  ops/ms
DateTimeFormatterParse.parseLocalDate              thrpt   15  5014.987 ± 424.759  ops/ms
DateTimeFormatterParse.parseLocalDateTime          thrpt   15  3821.083 ± 390.928  ops/ms
DateTimeFormatterParse.parseLocalDateTimeWithNano  thrpt   15  3529.090 ± 209.195  ops/ms
DateTimeFormatterParse.parseLocalTime              thrpt   15  4275.904 ± 335.752  ops/ms
DateTimeFormatterParse.parseLocalTimeWithNano      thrpt   15  4596.255 ± 195.175  ops/ms
DateTimeFormatterParse.parseOffsetDateTime         thrpt   15  2330.924 ± 152.061  ops/ms
DateTimeFormatterParse.parseZonedDateTime          thrpt   15  1837.753 ± 107.873  ops/ms

# d8742d7 (this pr)
Benchmark                                           Mode  Cnt     Score     Error   Units
DateTimeFormatterParse.parseInstant                thrpt   15  2900.168 ±  56.079  ops/ms
DateTimeFormatterParse.parseLocalDate              thrpt   15  9787.592 ± 384.437  ops/ms
DateTimeFormatterParse.parseLocalDateTime          thrpt   15  5046.838 ± 271.451  ops/ms
DateTimeFormatterParse.parseLocalDateTimeWithNano  thrpt   15  3963.050 ± 434.662  ops/ms
DateTimeFormatterParse.parseLocalTime              thrpt   15  8196.707 ± 329.547  ops/ms
DateTimeFormatterParse.parseLocalTimeWithNano      thrpt   15  8387.213 ± 652.292  ops/ms
DateTimeFormatterParse.parseOffsetDateTime         thrpt   15  3291.076 ± 294.889  ops/ms
DateTimeFormatterParse.parseZonedDateTime          thrpt   15  2069.595 ± 293.385  ops/ms


# 3. Performance Comparison


Performance Comparison: b6495573e9dc5470df268b63f8e7a93f38406cd2 vs d8742d7514abfe0e36f105fa7310fdb1755ae546

| Benchmark | b6495573e9dc5470df268b63f8e7a93f38406cd2 | d8742d7514abfe0e36f105fa7310fdb1755ae546 | Improvement Factor |
| --- | --- | --- | --- |
| DateTimeFormatterParse.parseInstant | 2066.130 ± 126.134 | 2900.168 ± 56.079 | 1.404x |
| DateTimeFormatterParse.parseLocalDate | 5014.987 ± 424.759 | 9787.592 ± 384.437 | 1.952x |
| DateTimeFormatterParse.parseLocalDateTime | 3821.083 ± 390.928 | 5046.838 ± 271.451 | 1.321x |
| DateTimeFormatterParse.parseLocalDateTimeWithNano | 3529.090 ± 209.195 | 3963.050 ± 434.662 | 1.123x |
| DateTimeFormatterParse.parseLocalTime | 4275.904 ± 335.752 | 8196.707 ± 329.547 | 1.919x |
| DateTimeFormatterParse.parseLocalTimeWithNano | 4596.255 ± 195.175 | 8387.213 ± 652.292 | 1.825x |
| DateTimeFormatterParse.parseOffsetDateTime | 2330.924 ± 152.061 | 3291.076 ± 294.889 | 1.412x |
| DateTimeFormatterParse.parseZonedDateTime | 1837.753 ± 107.873 | 2069.595 ± 293.385 | 1.126x |

java/time/tck/java/time/temporal/TCKWeekFields.java
java/time/tck/java/time/temporal/TCKIsoFields.java
java/time/tck/java/time/temporal/TCKJulianFields.java
java/time/tck/java/time/format/TCKDateTimeParseResolver.java
java/time/tck/java/time/format/TCKLocalizedFieldParser.java
java/time/tck/java/time/format/TCKDateTimeFormatters.java
java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java

The existing tests above can cover the cases where there are no non-ChronoFields, so no additional tests are needed.

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

PR Comment: https://git.openjdk.org/jdk/pull/28471#issuecomment-3571582110
PR Comment: https://git.openjdk.org/jdk/pull/28471#issuecomment-3573936930


More information about the i18n-dev mailing list