在啥情况下 Marshal.SizeOf 在堆上分配?
Posted
技术标签:
【中文标题】在啥情况下 Marshal.SizeOf 在堆上分配?【英文标题】: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<T>
的 IL:
呼叫转至外部SizeOf(Type t);
什么可能导致堆分配?我唯一的假设是拳击,但我在这里看不到任何拳击。 GetType()
should not allocate
【问题讨论】:
【参考方案1】:你提到的关于GetType()
分配行为的链接说它不会每次都分配一个新实例,它确实不说它根本不分配。 p>
第一次在特定类型的对象上调用 GetType()
将导致分配一个新的 RuntimeType
实例来表示该类型,但这是一次性分配和随后的 GetType()
对对象的调用该类型的将返回现有实例。
【讨论】:
嗯,我进行了更多测试,发现它仍然会在后续运行中分配。关于为什么会发生这种情况的更多想法? @KreonZZ - 在我的测试中,它只在第一次调用GetType()
时分配。如果您看到不同的东西,您将需要提供更多详细信息,说明您调用 Marshal.SizeOf<T>()
的确切代码以及您如何衡量分配。
代码没什么特别的,它将泛型 T 限制为 struct 然后调用 Marshal。我做了一个哈希集来检查有多少独特的类型,它只有 20 个。20 种类型不能产生 3Mb 的 GetSize 垃圾,我认为单声道有一些我不知道【参考方案2】:
使用 dotMemory 并在启用“从开始时收集内存分配和流量数据”选项的情况下分析您的应用程序。然后看"Allocations" view。它会以字节/对象的准确性向您显示所有分配。
您能否告诉我 dotMemory/dotTrace 中的数据是否与您的情况不同?
【讨论】:
以上是关于在啥情况下 Marshal.SizeOf 在堆上分配?的主要内容,如果未能解决你的问题,请参考以下文章
Marshal.AllocHGlobal VS Marshal.AllocCoTaskMem,Marshal.SizeOf VS sizeof()