【问题标题】:Under which conditions Marshal.SizeOf allocates on the heap?在什么情况下 Marshal.SizeOf 在堆上分配?
【发布时间】:2021-07-06 08:06:29
【问题描述】:

所以我有来自 dotTrace 的非常奇怪的追踪数据:

这是结构:

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));
}

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

这里是 mono 的 mscorlib Marshal.SizeOf&lt;T&gt; 的 IL: 呼叫转至外部SizeOf(Type t);

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

【问题讨论】:

    标签: c# unity3d mono marshalling unmanaged-memory


    【解决方案1】:

    你提到的关于GetType() 分配行为的链接说它不会每次都分配一个新实例,它确实说它根本不分配。 p>

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

    【讨论】:

    • 嗯,我进行了更多测试,发现它仍然会在后续运行中分配。关于为什么会发生这种情况的更多想法?
    • @KreonZZ - 在我的测试中,它只在第一次调用GetType() 时分配。如果您看到不同的东西,您将需要提供更多详细信息,说明您调用 Marshal.SizeOf&lt;T&gt;() 的确切代码以及您如何衡量分配。
    • 代码没什么特别的,它将泛型 T 限制为 struct 然后调用 Marshal。我做了一个哈希集来检查有多少独特的类型,它只有 20 个。20 种类型不能产生 3Mb 的 GetSize 垃圾,我认为单声道有一些我不知道
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-13
      • 2016-12-22
      • 2012-07-21
      • 2016-06-04
      • 1970-01-01
      • 2012-02-26
      • 2014-05-31
      • 2017-06-11
      相关资源
      最近更新 更多