Under which conditions Marshal.SizeOf allocates on the heap?

98 Views Asked by At

So I have very weird tracing data from dotTrace: enter image description here

Here is the struct:

public struct TargetStruct : SomeInterface
{
    private RigidTransform rt;
    public RoundBounds rb;
    public int Start;
    public Bool IsEnabled;
    public TypeEnum TheType;
}
//
// Nested types
//
public struct RoundBounds : SomeInterface
{
    public float3 Center;
    public float Radius;
    public float RadiusSq;
}
public struct Bool : IEquatable<Bool>, SomeInterface
{
    [MarshalAs(UnmanagedType.I1)]
    private bool value;
}
public enum TypeEnum : byte
{
    None,
    Type1,
    Type1
}
public struct RigidTransform
{
    public quaternion rot;
    public float3 pos;
    public static readonly RigidTransform identity = new RigidTransform(new quaternion(0f, 0f, 0f, 1f), new float3(0f, 0f, 0f));
}

This runs under Unity's mono 2019.4.12-mbe, if it is relevant, Unity generates project targeting 4.7.1. Struct is being passed down to SizeOf via generic methods with constraints where T: struct, though this should be irrelevant.

Here is IL of mono's mscorlib Marshal.SizeOf<T>: enter image description here Call is forwarded to external SizeOf(Type t);

What can possible cause heap allocations? My only assumption is boxing, but I cant see any boxing here. GetType() should not allocate

2

There are 2 best solutions below

3
Iridium On BEST ANSWER

The link you refer to regarding the allocation behavior of GetType() says that it doesn't allocate a new instance every time, it does not say it doesn't allocate at all.

The first time you call GetType() on an object of a particular type will result in the allocation of a new RuntimeType instance to represent the type, but it's a one-off allocation and subsequent GetType() calls on objects of that type will return the existing instance.

0
Ed Pavlov On

Take dotMemory and profile your application with "Collect memory allocation and traffic data from start" option enabled. Then look at "Allocations" view. It'll show you all allocations with accuracy to byte/object.

Could you please tell me if data in dotMemory/dotTrace differs in your case?