Skip to content

Suboptimal field layout when an object is wrapped in a struct #63005

Description

@MihaZupan

Consider the following type definitions:

public abstract class Base1
{
    private object _object;
    private byte _byte;
}
public abstract class Base2
{
    private WrappedObject _object;
    private byte _byte;

    private struct WrappedObject
    {
        private object _object;
    }
}

public sealed class Derived1 : Base1
{
    private byte _byte;
}
public sealed class Derived2 : Base2
{
    private byte _byte;
}

Derived1 will group the two byte fields together with 6 bytes of padding.
Derived2 will store the two byte fields separately and add 7 bytes of padding after each one.
As a result, Derived1 takes up 16 bytes (after the header and MT), but Derived2 takes up 24.

image
image

Is such a layout intentional, or just a random inefficiency?

Hit in #62981

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Dec 20, 2021
  2. jkoritzinsky commented on Dec 21, 2021

    @jkoritzinsky
    Member

    This layout (at least as of writing this response) is intentional. The auto-layout algorithm places primitive and ref (object or class-types) fields first and user-defined value types last, which is why you see WrappedObject after the padding in Derived2. There’s also a mechanism for derived types to place small primitive fields in any trailing padding in the base type, which is what you see happening in the Derived1 case.

    This is something that can be improved on, it just takes a bit of work (and can only be done when we take an R2R breaking change, so either some time in the next few months or after .NET 7).

  3. added a commit that references this issue on Feb 1, 2022
  4. removed
    untriagedNew issue has not been triaged by the area owner
    on Jul 6, 2022
  5. added this to the Future milestone on Jul 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions