什么时候对C#中的数组进行零填充操作?

时间:2012-02-03 09:56:36

标签: c# arrays performance initialization

在C#中考虑这个:

int[] a = new int[1024];

所有整数都将设置为0.传统上,这是通过高度优化的零填充操作(例如memset)完成的。但是,由于这个数组是由CLR分配的,我可以想到一个非常简单的优化; CLR可以维持一个归零的内存区域,以便在我们请求内存时跳过这个零填充。

现在,CLR会执行这样的优化吗? (我目前正在使用.NET 4.0)

3 个答案:

答案 0 :(得分:2)

CLR只分配一个bit more memory而不是托管堆消耗,然后如果它耗尽了托管堆的未分配内存,它将从操作系统请求更多内存。如果您的进程工作集已经很大并且您有大量未使用的内存可以收集垃圾,那么预备存在内存只会占用优势。然后,此内存可从托管堆中自由分配。 如果你的应用程序是这种情况,你应该考虑重用数组而不是删除它以避免在托管堆上重新分配。

答案 1 :(得分:2)

这在较低的水平上运作。 Windows保持低优先级内核线程活着,其唯一的工作是将内存页面的内容归零。称为“零页面线程”。这些页面保存在池中,可供任何为保留但未提交页面生成页面错误的进程使用。 Windows中的任何代码都受益于此,而不仅仅是托管代码。目的是安全性,而不是零映射内存页面的RAM内容将允许程序监视另一个进程的内存。

您的阵列不会发生这种情况,它太小了。它被分配在gen#0堆中,这是一个始终具有映射页面的堆。然而,大型数组在大对象堆中分配,大型为85,000字节,对于双数组而言为8000字节。 LOH分配可以利用将页面预初始化为零。它是否真的很难说,其源代码在任何地方都无法获得。我想它可能会考虑它节省的cpu周期数量。

答案 2 :(得分:1)

您是否看过为此代码生成的IL?可能会针对相关电话生成对newarr的调用。根据ECMA-355,newarr创建一个新的从零开始的一维数组,并将数组的元素初始化为适当类型的0。在这种情况下,由于它是int的数组,因此元素将在创建时初始化为0.