如果它的尺寸合理已知,是否值得初始化列表的集合尺寸?

问题描述:

如果合理地知道List<T>的集合大小,是否值得初始化?如果它的尺寸合理已知,是否值得初始化列表<T>的集合尺寸?

编辑:进一步解答这个问题,在阅读第一个答案之后,这个问题真的归结为什么是默认容量,以及增长操作是如何执行的,是否会使容量翻倍?

+0

只是因为你说“合理”而不是“绝对”,我会说不。 – 2010-02-11 21:21:47

+1

你会采用什么措施来确定wortwhileness?如果只是速度,运行一些测试,并告诉我们结果,请:-) IIRC每次填充时(二进制进程)该列表翻倍,所以这有一些开销 – TFD 2010-02-11 21:22:03

+1

反射器可以回答您编辑中的问题(答案似乎是0并且是(除了首次使用0 - > 4)) – AakashM 2010-02-11 21:54:26

是的,当你的List<T>变大时它变得很重要。确切的数字取决于元素类型和机器体系结构,让我们在32位机器上选择参考类型列表。每个元素将在内部数组中占用4个字节。该列表将以容量0和空数组开始。第一个Add()调用将容量增大到4,将内部阵列重新分配为16个字节。之后四次调用Add(),数组已满,需要重新分配。它使尺寸加倍,容量增长到8,数组大小为32字节。前面的数组是垃圾。

根据需要重复这些内部数组的几个副本将变成垃圾。

当数组增长到65,536字节(16,384个元素)时会发生一些特殊情况。接下来的Add()再次将尺寸加倍为131,072字节。这是一个超过“大型对象”(85,000字节)阈值的内存分配。现在不再在第0代堆上进行分配,它从大对象堆中取出。

LOH上的物体被特别处理。他们只是在第二代收集期间收集的垃圾。堆没有被压缩,移动这么大的块需要太多的时间。

根据需要重复多次LOH对象会变成垃圾。他们可以占用记忆很长一段时间,第二代收藏不会经常发生。另一个问题是这些大型块倾向于分割虚拟内存地址空间。

这并不是无止境的重复,迟早List类需要重新分配数组,并且它已经增长得如此之大以至于虚拟内存地址空间中没有留下空洞来适应数组。您的程序将以OutOfMemoryException发生爆炸。通常在所有可用虚拟内存耗尽之前。长话短说,通过在开始填充列表之前尽早设置容量,您可以预先保留大型内部阵列。你不会在大对象堆中获得所有那些尴尬的释放块,并避免碎片化。实际上,您可以在列表中存储更多的对象,并且您的程序运行更加精简,因为垃圾很少。只有当你有一个好主意名单时,才能做到这一点,使用你永远不会填充的大容量是浪费。

+2

非常翔实的答案,我不认为我曾经与列表超过10,000元素的工作,但现在如果我想我会需要这个知识将是非常有用的理解大的列表的含义。 – 2010-02-12 13:15:37

是,as per documentation

如果集合的大小可以是 估计,指定初始 容量无需 执行调整大小 操作,而将元素添加到 列表的数( T)。

+1

默认容量是多少? – 2010-02-11 21:31:46

+0

我认为它是“0”。可以检查任何时间使用列表(T)。容量支柱 – 2010-02-11 21:41:09

那么,它会阻止你列表中的值(这将是引用,如果元素类型是一个引用类型)不必随着列表的增长而偶尔复制。

如果这将是一个特别大的名单,并且你对尺寸有了一个很好的想法,它不会受到伤害。但是,如果估计的大小涉及额外的计算或任何大量的代码,我不会担心它,除非您发现它成为一个问题 - 它可能会分散代码的主要焦点,调整大小不会导致性能除非它是一个非常大的清单,否则你会做很多事情。