Skip to content

Parse common SIRI dateTime forms without DateTimeFormatter - #38

Merged
vpaturet merged 1 commit into
masterfrom
feat/zdt-adapter-manual
Oct 12, 2026
Merged

vpaturet merged 1 commit into
masterfrom
feat/zdt-adapter-manual

Conversation

@vpaturet

@vpaturet vpaturet commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This PR adds FastZonedDateTimeParser, a position-based parser for yyyy-MM-ddTHH:mm:ss[.fffffffff][Z|±HH:MM]. It reads the fields at fixed positions, uses no regular expressions and allocates nothing but the result. ZonedDateTimeAdapter.parse tries it first and falls back to the previous ZonedDateTime.parse / LocalDateTime.parse logic for any other ISO form (missing seconds, ±HH:MM:SS offsets, [Region] suffixes, lowercase t/z, extended years, ...) and for any out-of-range field, so results and exception types are unchanged. Local times without zone designator are resolved in the fast path exactly as the fallback does (ZonedDateTime.ofLocal with a UTC preferred offset).

The same approach is in use in netex-java-model: entur/netex-java-model#310.

Results

Measured on a SIRI-ET document (282 MB, 1.8 million xsd:dateTime values), JDK 25, -Duser.timezone=Europe/Oslo, JMH average time per parse:

before after
ns/op, all values 1079 ± 118 74 ± 7
ns/op, values with fraction 1156 ± 273 95 ± 12
time in ZonedDateTimeAdapter.parse for the whole dump ≈ 1.94 s ≈ 0.13 s

The fast path handles 100 % of the values in that dump (95.7 % plain ±HH:MM, 4.3 % with a 1–9 digit fraction). A regex-based variant was also measured and only halved the cost, so it was dropped.

End-to-end test

Full SiriXml.parseXml(InputStream) of the 282 MB tst dump (18,874 EstimatedVehicleJourney, 1.8 M dateTimes), -Duser.timezone=Europe/Oslo, -Xms6G -Xmx6G, 4 pinned cores, 5 interleaved JVM launches per arm × 5 measured parses after 3 warm-up:

metric master PR delta
wall per unmarshal, mean ± 95 % CI 7539 ± 224 ms 4849 ± 254 ms −35.7 % (×1.55)
wall, median 7413 ms 4554 ms
main-thread CPU, mean 7104 ms 4614 ms −35.1 %
young-gen allocation per unmarshal (GC log, approx.) 4.6 GB 1.0 GB −77 %
G1 pauses over 6 unmarshals 23 / 9.65 s 14 / 6.95 s

ZonedDateTimeAdapter.parse alone over the 1,795,022 real strings (5 JVMs per arm × 10 iterations): 906 ± 23 ns/op → 118 ± 10 ns/op (×7.7), consistent with the JMH figures in the description.

The end-to-end gain (≈ 2.7 s) is about twice the adapter-only saving (1.8 M × 0.79 µs ≈ 1.4 s); the rest comes from the removed allocation pressure (fewer and shorter G1 pauses while the whole document tree is live) and the formatter running cold inside JAXB rather than hot in a micro loop. Per-round medians were consistent across all five rounds (master 6983–8127 ms, PR 4290–5745 ms).

@vpaturet
vpaturet force-pushed the feat/zdt-adapter-manual branch from 3daa66b to aef7033 Compare October 9, 2026 09:39
@vpaturet vpaturet changed the title perf: parse common SIRI dateTime forms without DateTimeFormatter Parse common SIRI dateTime forms without DateTimeFormatter Oct 9, 2026
@vpaturet
vpaturet force-pushed the feat/zdt-adapter-manual branch from aef7033 to bc1c396 Compare October 9, 2026 09:46
Add FastZonedDateTimeParser, a position-based parser for
yyyy-MM-ddTHH:mm:ss[.fffffffff][Z|±HH:MM]. ZonedDateTimeAdapter tries it
first and falls back to the previous ZonedDateTime.parse / LocalDateTime
logic for any other form or out-of-range field, so results and exception
types are unchanged. Local times without zone designator are resolved
exactly as the fallback does.
@vpaturet
vpaturet force-pushed the feat/zdt-adapter-manual branch from bc1c396 to 1c644fc Compare October 12, 2026 11:52
@vpaturet
vpaturet marked this pull request as ready for review October 12, 2026 12:15
@vpaturet
vpaturet requested review from lassetyr and a balanced review from Copilot and removed request for Copilot October 12, 2026 12:20
@vpaturet
vpaturet merged commit dd893b5 into master Oct 12, 2026
11 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants