与.NET对象相关的固定开销在此SO问题中有更全面的概述:What is the memory overhead of a .NET Object为12或24字节,具体取决于您是处于32位还是64位进程。
也就是说,int, double, boolean
之类的基本值类型不会产生任何开销,因为它们是值类型。
您在应用程序中放置自定义struct
类型的位置在哪里?一方面,它们是价值类型,如int, double, boolean
以上[因此不应产生开销],但另一方面,它们间接来自System.Object
,因此(技术上)应该产生开销。
答案 0 :(得分:9)
将您放在一起的自定义结构类型留在哪里 你的申请?
它们与原始类型没有什么不同。除了他们拥有的领域之外,它们不会带来额外的开销。它们派生自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仍然可以自由地重新排序字段或将它们打包在一起。
答案 1 :(得分:7)
结构的大小由其字段的大小之和加上确定正确对齐的字段之间的填充,加上结构末尾的填充以确保它们的大小当struct存储在数组中时,仍然可以正确对齐。
因此,对于一个,结构并不完全不可能包含引用类型的字段。像一个字符串。在这种情况下,struct会更大,因为引用是引擎盖下的指针,占用8个字节而不是4个。
填充物是更加狡猾的细节。在32位模式下,变量不能指向优于4的对齐。double
和long
的问题,8字节类型很容易被错误对齐。特别是影响32位程序的性能,如果双重在L1高速缓存边界线上未对齐,则读取或写入速度可能是3倍。这也是C#内存模型中这些类型不是 atomic 的核心原因。在64位模式下不是问题,CLR必须确实提供8的对齐保证。
然而,CLR确实试图在32位模式下给这样的结构成员正确对齐,即使结构本身不能保证对齐。否则,具有隐式[StructLayout(LayoutKind.Sequential, Pack=8)]
属性的结构的副作用。 CLR源代码中的一个奇怪的是,执行此操作的C ++语句没有注释。我怀疑它是一个快速解决方案,对于低于恒星的非托管互操作性能,保持结构 blittable 对速度非常重要。
DateTime
和DateTimeOffset
发生了这种情况,编写它们的程序员出于非常神秘的原因应用了[StructLayout(LayoutKind.Auto)]属性。在DateTimeOffset的情况下可能是复制/粘贴错误。结构的布局现在将是不可预测的,它也变为LayoutKind.Auto,CLR重新排列字段以最小化结构大小。 可以在x64模式下导致额外的填充。
这些是不应该担心的晦涩的实现细节。
答案 2 :(得分:2)
字段'对齐可能会产生一些开销:
E.g。
public struct Test {
public Byte A;
public long B;
}
64位进程的大小 16 字节, 32位进程的 12 字节相应地(当我们只能期望 9 字节时);
答案 3 :(得分:1)
零。
除非由于对齐而存在差距,否则就会造成这些差距的成本。
但是否则结构就像字段是堆叠的单独变量一样。
虽然装箱,但您通过object
处理它,其开销与任何其他参考类型相同。