收集类型的初始容量,例如字典,列表

时间:2010-05-03 20:18:31

标签: c# .net memory-management collections object-initializers

.Net中的某些集合类型具有可选的“初始容量”构造函数参数。例如:

Dictionary<string, string> something = new Dictionary<string,string>(20);

List<string> anything = new List<string>(50);

我无法在MSDN上找到这些对象的默认初始容量。

如果我知道我只会在字典中存储12个左右的项目,那么将初始容量设置为20是不合理的呢?

我的理由是,假设容量增长的速度与StringBuilder的增长速度相同(每次容量达到时都会增加一倍),并且每次重新分配都很昂贵,为什么不预先设置大小来保存您的数据,还有一些额外的房间以防万一?如果初始容量是100,并且我知道我只需要十几个,那么好像其余的内存都没有分配。

4 个答案:

答案 0 :(得分:69)

如果未记录默认值,原因可能是最佳初始容量为实施细节,并且可能会在框架版本之间发生变化。也就是说,您不应该编写假定某个默认值的代码。

具有容量的构造函数重载适用于您比对类更清楚的情况。例如,如果您创建了50个值的集合并且知道此数字永远不会增加,则可以初始化容量为50的集合,因此如果默认容量较低,则不必调整大小。

也就是说,您可以使用Reflector确定默认值。例如,在.NET 4.0中(也可能是以前的版本),

  • 列表&lt; T&gt;初始化为容量为0.当添加第一个项目时,它将重新初始化为容量4.随后,只要达到容量,容量就会翻倍。

  • 字典&lt; T&gt;初始化的容量为0。但是它使用了一种完全不同的算法来增加容量:它总是将容量增加到素数。

答案 1 :(得分:9)

检查来源,List<T>Dictionary<TKey, TValue>的默认容量均为0.

答案 2 :(得分:9)

如果您知道尺寸,请告诉它;在大多数“小”案例中进行小规模优化,但对更大的集合有用。如果我正在投入“相当多”的数据,我会主要担心这一点,因为它可以避免分配,复制和收集多个数组。

大多数收藏品确实采用了倍增策略。

答案 3 :(得分:2)

ConcurrentDictionary(当前)和使用其构造函数设置初始大小的另一个问题是它的性能似乎受到阻碍。

例如,here's some example code and benchmarks我试过了。

我在我的机器上运行代码并获得了类似的结果。

也就是说,当指定初始大小时,在添加对象时它不会增加ConcurrentDictionary的速度。从技术上讲,我认为应该因为它不需要花时间或资源来调整自身的大小。

是的,它的运行速度可能不如普通的Dictionary快,但我仍然希望ConcurrentDictionary的初始大小设置为比没有设置初始大小的ConcurrentDictionary具有一致,更快的性能,尤其是当一个事先知道要添加到它的项目数量。

故事的寓意是设定初始尺寸并不总能保证性能的提升。