<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