Skip to content

TimeZoneInfo.GetSystemTimeZones() allocates 8MB on the GC heap (linux-x64) #132620

Description

@EgorBo

From OrchardCMS's gc dump.

long before = GC.GetAllocatedBytesForCurrentThread();
var zones = TimeZoneInfo.GetSystemTimeZones();
long after = GC.GetAllocatedBytesForCurrentThread();
Console.WriteLine(after - before);

outputs: 8 373 656. Seems like a lot. (same code on Windows is 0.6Mb).

On Ubuntu,  GetSystemTimeZones()  roughly does this:

  1. Enumerates roughly 500 IANA zones.
  2. Reads every corresponding TZif file.
  3. Allocates temporary parsing buffers: transition dates, type indexes, offset records, abbreviations, and lists.
  4. Eagerly converts every historical transition interval into a  TimeZoneInfo.AdjustmentRule .
  5. Builds the zone dictionary, result array, names, and read-only collection.
  6. Because this is the default overload, populates display names and sorts by  DisplayName .

The dump showed the dominant retained part:

• 498  TimeZoneInfo  objects
• 32,310  AdjustmentRule  objects: 3,360,240 bytes
• Their arrays: another 269,520 bytes
• 99.53% are Linux-style rules representing a single historical offset interval
• All are permanently retained in the global  TimeZoneInfo  cache

The remaining portion of the 8.37 MB includes temporary TZif parsing data, strings, dictionaries, sorting, and other supporting objects.  GetAllocatedBytesForCurrentThread()  measures everything allocated during the call, including objects that later die. Subsequent calls reuse the global cache and should allocate essentially nothing.

Possible optimizations:

  • Keep TZif transitions in compact arrays and materialize AdjustmentRule[] only when GetAdjustmentRules() is called.
  • Lazily parse historical transitions and initialize per-zone transition caches only when conversions need them.
  • Share immutable transition data between aliases or equivalent zones.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status
    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions