C#对象大小开销

Tom*_*Tom 8 c# c#-4.0

我正在努力优化内存消耗应用程序.与此相关,我对C#引用类型大小开销有疑问.

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

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

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

Ree*_*sey 16

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

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

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


Alo*_*aus 6

网上有一篇文章标题为"关于.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<N;i++)
{
  arr[i] = new object();
}
var ObjSize = (initial-GC.GetTotalMemory(false)-N*IntPtr.Size)/N 
Run Code Online (Sandbox Code Playgroud)

在.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))
Run Code Online (Sandbox Code Playgroud)

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