在一个32位的dot-net程序中,我想为一个类添加一个新字段。该领域将是一个 的字典< string,object> 。由于存在这个类的数千个实例,我想知道这需要多少额外的内存。对于大多数情况,我可能永远不会使用任何值填充此字段。
空字典需要多少内存?
答案 0 :(得分:2)
对于大多数情况,我可能永远不会用任何值填充此字段。
然后对于大多数实例,空引用将为4个字节。 8位是64位,如果你比你在答案中提到的32位细节更适应它。
空字典需要多少内存?
这是一个不同的问题,因为在这里你似乎用一个空字典填充它,这与不填充它不一样。大小会因库版本而异,但大约会有40个字节。
为什么这样呢?如果它很少使用,那么很少设置它。只有在它被写入时才设置它,否则将其保留为null,并让看起来读它的代码找到"不存在"回答null与空的回答相同。
public void Add(string key, object value)
{
if (_dict == null)
{
_dict = new Dictionary<string, object>();
}
_dict.Add(key, value);
}
public bool TryGetValue(string key, out object value)
{
if (_dict != null)
{
return _dict.TryGetValue(key, out value);
}
value = null;
return false;
}
答案 1 :(得分:1)
从不填充&#34;,我假设你的意思是:
Dictionary<string,object> myDic = null;
如果您关注内存使用情况,可能最好 - 在您知道需要新字典之前,不要实例化新字典。那么答案基本上只是在每个实例中保存变量引用所需的内存,这是微不足道的。
如果你做需要实例化字典,那么(当前)默认大小为零元素。您可以覆盖该初始容量,但除非您提出要求,否则我不会放弃算法的兔子扩展容量。
所以基本上,无论如何,你都会使用很少的内存。
答案 2 :(得分:1)
Dictionary<T, K>
是一种引用类型,这意味着实例在堆上分配并由句柄引用。
由于您未填充该字段,因此句柄将保留其默认null
值。因此,唯一的开销是句柄本身的大小,它与IntPtr
相同(32位运行时为32位,64位运行时为64位)。
通过在分配大量句柄后检查托管堆的大小,可以很容易地验证这一点:
var start = GC.GetTotalMemory(true);
var handles = new Dictionary<string, object>[100000];
var sizeApprox = (GC.GetTotalMemory(false) - start) / 100000.0;
GC.KeepAlive(handles);
Console.WriteLine("A handle takes {0:0.##} bytes", sizeApprox);
// Prints 4 in x86 mode and 8 in x64 mode