Skip to content

Skip repetetive LocalDate parsing - #300

Open
leonardehrenfried wants to merge 1 commit into
entur:masterfrom
leonardehrenfried:aggressive-local-time-cache
Open

leonardehrenfried wants to merge 1 commit into
entur:masterfrom
leonardehrenfried:aggressive-local-time-cache

Conversation

@leonardehrenfried

@leonardehrenfried leonardehrenfried commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Summary

LocalTimeISO8601XmlAdapter.unmarshal was showing up in real-world profiling as a hotspot: NeTEx documents contain a very large number of LocalTime values, and every one of them was going through DateTimeFormatter.parse, which is comparatively expensive.

Since a day only has 86,400 distinct whole-second times, this PR precomputes all of them once at class-load time:

  • TIMES_BY_SECOND_OF_DAY — a LocalTime[86400] array indexed by second-of-day, used to hand back a canonical, deduplicated instance.
  • TIME_BY_STRING — a Map<String, LocalTime> from the formatted "HH:mm:ss" string to that same canonical instance.

Flame graph

Before

image

After

image

Real-world improvement

When using this improvement in an OTP graph build with a very large (50GB!) NeTEx feed this leads to some very noticeable graph build improvements.

Before

Graph building took 18m58s697ms.

After

Graph building took 17m28s267ms

So 90 seconds was spent in repeatedly parsing LocalTimes!

Memory tradeoff

The previous cache was a ConcurrentHashMap populated lazily — it only held entries for times actually seen, so a typical document with a handful of distinct times cost next to nothing.

The new cache is precomputed unconditionally at class-load time, so it always costs the same, whether or not the times are ever used.

Measured via heap-delta on class load:

  • Old adapter (lazy cache, empty at startup): ~2.3 MB (mostly DateTimeFormatter class loading)
  • New adapter (precomputed cache): ~13.5 MB

Net additional cost: ~11-12 MB, permanent for the life of the JVM. This is a fixed one-time cost, not per-instance, and trivial relative to typical heap sizes — but worth calling out since it's paid upfront rather than proportionally to usage.

cc @flaktack

Ref: noi-techpark/opendatahub-mentor-otp#330

@leonardehrenfried leonardehrenfried changed the title Skip parsing of repetetive LocalDate parsing Skip repetetive LocalDate parsing Sep 11, 2026
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.

1 participant