假设在x64 Windows框上使用Visual Studio和C#的最新版本,并分配大量数据。
当然,当使用默认的构建设置进行编译时(如下图VS 2019 Preview 2.1所示),当进程达到4 GB时,用户虚拟地址空间将用完。这是预料之中的,其原因已在here中进行了讨论。
例如,可以通过创建几百个简单的数组来完成分配本身,每个数组包含几百万个int
元素。
我想了解的是为什么选择Any CPU/Prefer 32-bit
作为默认构建选项。我还注意到VS 2015也具有相同的默认设置,很可能是自VS 11之后发布的每个版本,如here所述。
通常会问的问题是“什么是AnyCPU ...?”并得到了反复的回答(1 2 3 4 5),简要介绍了定位x86
/ {{1 }} / x64
。但是对于为什么Any CPU + Prefer 32-bit
被选为VS中的默认设置,我还没有一个明确的答案。
请仔细阅读默认情况下针对x64进行构建的原因:
Any CPU + Prefer 32-bit
的数组),实际上并非如此。当然,对数组本身的引用将是双精度的(8个字节而不是4个字节),仅此而已。根据{{3}}(“内存管理”一章),页面表结构中的PFN条目本身在x86和x64体系结构上均为64位宽,只有3(对于x86)对4(对于x64)表的级别,用于将虚拟地址解析为物理地址。至于引用的数据,大小相同(每个int
值4个字节)。因此,分配20个1000万个int
数组将大致转换为托管堆上的两种体系结构使用的800 MB。实际上,刚刚描述的简单示例的x64版本的总体提交大小与经过测试的x86大致相同(比较后,顶部x64,下方x86;并且忽略了4 GB的块,该块只是保留状态,用于x64版本)。有趣的是,在x64上运行32位进程时,该进程中的每个线程最终都会有2个堆栈,一个32位wow64堆栈和一个64位堆栈,因此从堆栈角度来看会导致更高的内存消耗。
"Windows Internals" book int
之前)提供了指向here的链接(本文于2017年更新)写作)。被引用的文章还显示了兼容性矩阵,但这仅适用于UWP。特别是关于ARM体系结构是使用Prefer 32-bit
进行构建输出的现成目标,MS recommendation的漂亮表对此提供了支持。 this answer也被大量引用,显示了.NET 4.5带来的更改以及对ARM的影响。AnyCPU/Prefer 32-bit
编译的程序集。 最后,默认的Any CPU/Prefer 32-bit
设置很可能是一个折衷方案,并且由于某些其他更重要的事情而牺牲了大容量(> 4 GB)的内存访问。
尽管在Win10上x64进程用户模式虚拟地址空间的限制是128 TB,并且4 GB的物理RAM在当今的入门级笔记本电脑中成为标准配置,因此可能失去所有额外RAM(最大物理内存)的优势。 Windows版本的内存限制为here)。