Skip to content

DateComponents memory usage considerations #302

Open
@hassila

Description

@hassila

So we are looking at using much more of Foundation now thanks to the Swift rewrite - looking at some of the implementation, one thing that is concerned us is some of the choices of internal representation of data that is unnecessarily large.

To take just one obvious example (exluding the layout overhead for the optional enum, but just looking at data storage):

https://github.com/apple/swift-foundation/blob/main/Sources/FoundationEssentials/Calendar/DateComponents.swift

public struct DateComponents : Hashable, Equatable, Sendable {
...
    internal var _era: Int?
    internal var _year: Int?
    internal var _month: Int?
    internal var _day: Int?
    internal var _hour: Int?
    internal var _minute: Int?
    internal var _second: Int?
    internal var _nanosecond: Int?
    internal var _weekday: Int?
    internal var _weekdayOrdinal: Int?
    internal var _quarter: Int?
    internal var _week: Int?
    internal var _weekOfMonth: Int?
    internal var _weekOfYear: Int?
    internal var _yearForWeekOfYear: Int?
...

~960 bits

Using 64-bits (for most platforms) for the majority of these is just massive overkill in terms of storage space as they are well-defined entities and 8/16/32 bits are sufficient (without resorting to any bit-stuffing) by just appropriate declaration;

public struct DateComponents : Hashable, Equatable, Sendable {
...
    internal var _era: Int32?  // likely overkill
    internal var _year: Int32?
    internal var _month: Int8?
    internal var _day: Int8?
    internal var _hour: Int8?
    internal var _minute: Int8?
    internal var _second: Int8?
    internal var _nanosecond: Int32?
    internal var _weekday: Int8?
    internal var _weekdayOrdinal: Int8?
    internal var _quarter: Int8?
    internal var _week: Int8?
    internal var _weekOfMonth: Int8?
    internal var _weekOfYear: Int8?
    internal var _yearForWeekOfYear: Int8?
...

~192 bits

That's a 5x difference.

One can argue for how many instances one might use for this particular use case etc, but for a foundational library it'd be nice to have an efficient implementation (both in time&space) by default, especially when it can just be declared.

Perhaps this is just a singular instance, haven't gone through and reviewed everything, but it was a bit concerning so wanted to raise the discussion.

Without having all the details, if this is due to bridging to legacy (ahem) languages, maybe there are some other way?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions