.NET自定义结构类型的内存开销是多少?

有一个与.NET对象相关的固定开销,在这个问题中有更全面的概述: .NET对象的内存开销是12或24字节,具体取决于你是在32位还是64位进程。

也就是说,像int, double, boolean等基本值类型不会产生开销,因为它们是值类型

在您的应用程序中放置自定义struct类型的位置在哪里? 一方面,它们是值类型,如上面的int, double, boolean [所以不应该产生开销],但另一方面它们间接地从System.Object派生,因此(技术上)应该产生开销。

在您的应用程序中放置自定义结构类型的位置在哪里?

它们与原始类型没有什么不同。 除了他们拥有的领域之外,它们不会带来额外的开销。 它们从object派生的事实并不意味着它们会产生引用类型携带的开销,即方法表指针和同步根块。

你可以使用Marshal.SizeOf来测试它:

 void Main() { var f = new Foo(); Console.WriteLine(Marshal.SizeOf(f)); } public struct Foo { public int X { get; set; } public int Y { get; set; } } 

这将以32位模式打印8,这恰好是两个整数值(每个4个字节)。

注意Marshal.SizeOf将输出非托管对象的大小。 CLR仍然可以自由地重新排序字段或将它们打包在一起。

结构的大小由其字段大小的总和加上正确对齐的字段之间的填充,加上结构末尾的填充,确保在结构存储时它们仍然正确对齐数组。

因此,对于一个,结构并不完全不可能包含引用类型的字段。 像一个字符串。 在这种情况下,struct会更大,因为引用是引擎盖下的指针,占用8个字节而不是4个字节。

衬垫是更加狡猾的细节。 在32位模式下,变量不能指向优于4的对齐。 doublelong ,8字节类型的问题很容易被错误对齐。 特别是影响32位程序的性能,如果双重在L1高速缓存边界线上未对齐,则读取或写入速度可能是3倍。 这也是C#内存模型中这些类型不是primefaces的核心原因。 在64位模式下不是问题,CLR必须并确实提供8的对齐保证。

然而,CLR确实试图在32位模式下给这样的结构成员正确对齐,即使结构本身不能保证对齐。 否则,结构的副作用具有隐式[StructLayout(LayoutKind.Sequential, Pack=8)]属性。 CLR源代码中的一个奇怪的地方,执行此操作的C ++语句没有注释。 我怀疑它是一个快速修复不到恒星非托管互操作性能 ,保持结构blittable对速度非常重要。

然而,如果结构包含一个本身就是没有顺序布局的结构的成员,那么CLR就会放弃。 值得注意的是,这发生在DateTimeDateTimeOffset ,编写它们的程序员出于非常神秘的原因对它们应用了[StructLayout(LayoutKind.Auto)]属性。 在DateTimeOffset的情况下可能是复制/粘贴错误。 结构的布局现在将是不可预测的,它也变为LayoutKind.Auto,CLR重新排列字段以最小化结构大小。 这可能会导致x64模式下的额外填充。

这些是模糊的实现细节,你永远不应该担心。

字段的对齐可能会有一些开销:

https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute(v=vs.100).aspx

例如

  public struct Test { public Byte A; public long B; } 

将在64位进程上大小为16字节,在32位进程上相应地为12个字节(当我们只能期望9个字节时);

零。

除非由于对齐而存在间隙,否则就是这些差距的成本。

但是否则结构就像字段是堆栈上布局的单独变量一样。

虽然它是盒子,你通过object处理它,它具有与任何其他引用类型相同的开销。