Skip to content

Cache ZoneId in ZonedDateTimeAdapter to reduce allocation pressure#34

Merged
vpaturet merged 1 commit into
masterfrom
cache_zone_id_in_zoned_date_time_adapter
Feb 27, 2026
Merged

Cache ZoneId in ZonedDateTimeAdapter to reduce allocation pressure#34
vpaturet merged 1 commit into
masterfrom
cache_zone_id_in_zoned_date_time_adapter

Conversation

@vpaturet

@vpaturet vpaturet commented Feb 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Cache ZoneId.systemDefault() and ZoneOffset.ofHours(0) as static final constants in ZonedDateTimeAdapter instead of calling them on every parse() invocation.

Motivation

JFR profiling of OTP2 with a live SIRI-ET feed showed that ZonedDateTimeAdapter.parse() consumed 5.9% of total CPU during real-time processing. The root cause is ZoneId.systemDefault(), which internally calls TimeZone.getDefault() — this clones the ZoneInfo object on every call. With thousands of datetime fields per SIRI message, this produced ~717 MB of sampled ZoneInfo allocations and ~3.9 GB of ThreadLocalMap$Entry allocations over an 11-minute profiling window (~150 MB/s total allocation rate).

Caching the ZoneId and ZoneOffset as class-level constants eliminates this per-call overhead entirely.

Trade-off

By caching ZoneId.systemDefault() at class load time, the default zone is resolved once and reused for the lifetime of the JVM. This means that any runtime changes to the default timezone (via TimeZone.setDefault() or System.setProperty("user.timezone", ...)) will not be picked up by ZonedDateTimeAdapter. In practice this is a non-issue for server applications like OTP where the timezone is set at startup and never changed, but it is a behavioural change worth noting.

ZoneId.systemDefault() internally calls TimeZone.getDefault() which
clones the ZoneInfo object on every invocation. Since parse() is called
for every datetime field in SIRI XML messages, this creates significant
allocation pressure. Cache the default ZoneId and ZoneOffset as static
final constants to eliminate this per-call overhead.
@vpaturet vpaturet requested a review from lassetyr February 27, 2026 14:13
@vpaturet vpaturet merged commit 3846706 into master Feb 27, 2026
10 of 11 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