C#对象大小开销

我正在努力优化内存消耗应用程序。 关于这一点,我对C#引用类型大小开销有疑问。

C#对象消耗与其字段一样多的字节,以及一些额外的管理开销 。 我认为不同的.NET版本和实现的管理开销可能不同。

您知道C#对象(C#4.0和Windows 7和8环境)的管理开销是大小(或者如果开销是可变的最大大小)吗?

32位或64位.NET运行时的管理开销是否不同?

通常,GC为每个对象分配8或12字节的开销。 syncblk有4个字节,32位运行时有4个字节,64位运行时有8个字节。 有关详细信息,请参阅“钻入.NET Framework内部 ”的“ObjectInstance”部分, 以了解CLR如何在MSDN杂志上创建运行时对象 。

请注意,实际引用也会在32位或64位.NET运行时更改。

此外,可能有填充类型以适应地址边界,但这很大程度上取决于所讨论的类型。 这也可能导致对象之间出现“空白空间”,但是由运行时(主要是,虽然您可以使用StructLayoutAttribute影响它)来确定数据的对齐时间和方式。

在线有一篇文章标题为“关于.NET对象和在AppDomains之间共享的真相”,它显示了一些转子源代码和一些实验对象并通过普通指针在appdomains之间共享它们的结果。

http://geekswithblogs.net/akraus1/archive/2012/07/25/150301.aspx

  • 所有32位版本的CLR都有12个字节
  • 所有64位版本的CLR都有24个字节

您可以通过向数组中添加数百万个对象(N)来轻松地进行测试。 由于指针大小已知,您可以通过除以值来计算对象大小

var intial = GC.GetTotalMemory(true) const int N=10*1000*1000; var arr = new object[N]; for(int i=0;i 

在.NET平台上获得近似值。

对象大小实际上是一个允许GC对最小对象大小进行假设的定义。

 \sscli20\clr\src\vm\object.h // // The generational GC requires that every object be at least 12 bytes // in size. #define MIN_OBJECT_SIZE (2*sizeof(BYTE*) + sizeof(ObjHeader)) 

对于例如32位,这意味着最小对象大小为12字节,这确实留下4字节的空洞。 对于空对象,此孔为空,但如果向空类添加例如int,则填充该对象并且对象大小保持为12个字节。

对象有两种类型的开销:

  • 用于处理对象的内部数据。
  • 数据成员之间的填充。

内部数据是两个指针,因此在一个32位应用程序中是8个字节,在一个64位应用程序中是16个字节。

数据成员被填充,以便它们在偶数地址边界上开始。 例如,如果您在类中有一个byte和一个int ,则该byte可能用三个未使用的字节填充,以便int在下一个机器字边界开始。

类的布局由JIT编译器根据系统的体系结构确定(并且可能在框架版本之间有所不同),因此C#编译器不知道它。