据我所知,在32位机器上,指针占用4个字节(32位)。但是,当我在我的应用程序上运行CLRProfiler时,令我惊讶的是,它显示分配的内存为32个字节,仅用于保存一个接口指针。
从上面的图片可以看出,377910个对象消耗了12 MB,这意味着每个对象32个字节。 我在这里错过了什么吗?
答案 0 :(得分:0)
引用(而不是指针)存储了其他内容,例如C#'lock'关键字的Monitor。
答案 1 :(得分:0)
每个对象的开销。此外,您必须考虑CLR不时填充。见Getting the size of a field in bytes with C#
同样,List会在内部保留更多内存,因为它当前使用。
答案 2 :(得分:0)
尝试增加细节以查看它是否包括引用的实际对象的大小。
相比之下,请尝试以下程序:
class MemTest
{
private static object[] TakeUpSpace = new object[1024 * 1024];
public static void Main(string[] args)
{
var arr = TakeUpSpace;//make sure it's instantiated.
Console.ReadKey(true);//keep running so we can profile.
}
}
在32位机器上进行分析显示一个4MB大小的阵列 - 4 * 1024 * 1024,但没有引用实际对象。
但是这个:
class MemTest
{
private static object[] TakeUpSpace = new object[1024];
public static void Main(string[] args)
{
var arr = TakeUpSpace;//make sure it's instantiated.
for(var i = 0; i != 1024; ++i)
arr[i] = new object();
Console.ReadKey(true);//keep running so we can profile.
}
}
显示数组为16KB。 object[]
本身是1024 * 4 = 4KB,但每个对象至少有3 *指针大小(字段大小最小为一个指针大小,加上每个对象有两个指针大小的标题)
要求解释标题。
每个.NET对象显然都包含为其定义的字段。如果没有字段,或者字段小于引用的大小,那么它至少会占用那么多。
每个.NET对象都包含一个同步块,其中包含有关是否保留锁定的信息,以及用于编组的其他一些信息。
每个.NET对象都包含一个类型句柄,我们可以从中找出它的类型,虚拟成员的实现以及其他与类型相关的信息。
因此,当你有一个实际的对象 - 而不是一个空引用时,你可以保证为该对象占用至少12字节的内存,同时还有4个用于引用它的内容(当然可以有更多内存)而不是一个引用同一个对象)。如果对象有更多的字段或更大的字段,你可能会占用更多的字段,而且经常是。