C#中的数组何时进行零填充操作
本文关键字:填充 操作 何时进 数组 | 更新日期: 2023-09-27 18:22:25
在C#中考虑这一点:
int[] a = new int[1024];
所有整数都将设置为0。传统上,这是通过高度优化的零填充操作(例如memset
)来完成的。然而,由于这个数组是由CLR分配的,我可以想到一个非常直接的优化;CLR可以维护一个归零的内存区域,以便在我们请求内存时跳过这种零填充。
现在,CLR是否执行这样的优化?(我目前使用的是.NET 4.0)
这在一个低得多的级别上运行。Windows使一个低优先级内核线程保持活动状态,该线程的唯一任务是清空内存页的内容。称为"零页线程"。这些页面保存在一个池中,可供为保留但未提交的页面生成页面错误的任何进程使用Windows中的任何代码都可以从中受益,而不仅仅是托管代码。其目的是安全性,而不是将映射内存页的RAM内容归零将允许程序监视另一个进程的内存。
你的数组不会发生这种情况,因为它太小了。它被分配到gen#0堆中,这个堆将始终具有映射的页面。然而,大型数组在大型对象堆中分配,大型是85000字节,8000字节用于双数组。LOH分配可以利用将页面预初始化为零的优势。很难说它是否真的做到了,因为它的源代码在任何地方都不可用。我认为这可能是考虑到它节省的cpu周期数量。
CLR只分配比托管堆消耗的内存多一点的内存,然后如果它耗尽了托管堆的未分配内存,它将向操作系统请求更多内存。只有当您的进程工作集已经很大,并且您有大量未使用的内存被垃圾收集时,预调内存才会发挥作用。然后,该内存可以从托管堆中自由分配。如果您的应用程序是这种情况,您应该考虑重用数组,而不是丢弃它,以避免在托管堆上重新分配。
您看过为该代码生成的IL吗?可能会为所讨论的呼叫生成对newarr
的呼叫。根据ECMA-355,newarr
创建一个新的基于零的一维数组,并将数组的元素初始化为适当类型的0。在这种情况下,由于它是int
的数组,因此在创建时元素将初始化为0。