在什么条件下 Marshal.SizeOf 在堆上分配?

问题描述

所以我有来自 dottrace 的非常奇怪的跟踪数据:

enter image description here

这是结构:

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,1f),new float3(0f,0f));
}

这在 Unity 的单声道 2019.4.12-mbe 下运行,如果相关,Unity 会生成面向 4.7.1 的项目。结构通过具有约束 where T: struct 的泛型方法传递给 SizeOf,尽管这应该无关紧要。

这是 Mono 的 mscorlib Marshal.SizeOf<T> 的 IL:

enter image description here

呼叫被转接到外部 SizeOf(Type t);

什么可能导致堆分配?我唯一的假设是拳击,但我在这里看不到任何拳击。 GetType() should not allocate

解决方法

您参考的关于 GetType() 分配行为的链接说它不会每次都分配一个新实例,它not 说它根本不分配。

第一次对特定类型的对象调用 GetType() 将导致分配一个新的 RuntimeType 实例来表示该类型,但它是一次性分配和后续 {{ 1}} 对该类型对象的调用将返回现有实例。

,

使用 dotMemory 并在启用“从开始收集内存分配和流量数据”选项的情况下分析您的应用程序。然后看"Allocations" view。它会准确地向您显示字节/对象的所有分配。

您能否告诉我 dotMemory/dotTrace 中的数据是否与您的情况不同?