Skip to content

Proposal: Use padding to optimize optional type sizes #5162

Closed
@iansimonson

Description

@iansimonson

Currently in Zig optional pointer types get optimized to a regular pointer size. Effectively @sizeOf(*T) == @sizeOf(?*T). This is not the case for non-pointer types.

From some testing it seems the optional version of a type is the size of the type plus an extra field. More preciselyassert(@sizeOf(?T) == @sizeOf(T) + @alignOf(T)); For primitive types this is probably the best we can do unless there's something like the Explicit Sentinel Optionals proposed by @SpexGuy in #3806

However, for structs this can have some drastic effects depending on the alignment.

Example 0: Normal alignment optional:

const S = struct {
    a: u8,
};

test "Alignment" {
    std.debug.assert(@sizeOf(S) == 1);
    std.debug.assert(@sizeOf(?S) == 2);
}

Example 1: Large alignment optional:

const S = struct {
    a: u8 align(64),
};

test "Alignment" {
    std.debug.assert(@sizeOf(S) == 64);
    std.debug.assert(@sizeOf(?S) == 128);
    std.debug.assert(@sizeOf(?S) == @sizeOf(S) + @alignOf(S));
}

I'm not sure how feasible it is, but given Zig doesn't have a stable ABI for its own structs it should be possible to optimize an optional type's layout and size to use the generated padding to host the extra optional field.

This would effectively bring the @sizeOf(?S) in example 2 down to 64 and shouldn't have any issues with e.g. var set_of_s: [100]S = undefined; as the type S would stay properly aligned.

Of course it won't always be possible to do this optimization, in which case the optional type would have to add the additional field as normal.

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions