.net NET是否正确处理具有许多小对象的内存分页?

.net NET是否正确处理具有许多小对象的内存分页?,.net,memory,out-of-memory,.net,Memory,Out Of Memory,我曾多次开发过应用程序,这些应用程序具有非常大的分支或链接结构,每个小对象的大小小于1kb,或者1只是创建对象,或者2创建并访问对象 在这两种情况下,一旦物理可用RAM用完,应用程序要么完全停止,要么彻底抛出内存 我的理解是,一旦物理RAM耗尽,就应该进行分页,虽然速度非常慢,但程序应该继续工作。特别是,我既不尝试分配大型对象,也不使用超过2g对象的数组或列表。我不确定这一限制现在是否仍然适用 我写了一个小测试程序,它可以连续分配和存储1GB的内存块。由于.NET似乎延迟了分配,我还用数据填充了

我曾多次开发过应用程序,这些应用程序具有非常大的分支或链接结构,每个小对象的大小小于1kb,或者1只是创建对象,或者2创建并访问对象

在这两种情况下,一旦物理可用RAM用完,应用程序要么完全停止,要么彻底抛出内存

我的理解是,一旦物理RAM耗尽,就应该进行分页,虽然速度非常慢,但程序应该继续工作。特别是,我既不尝试分配大型对象,也不使用超过2g对象的数组或列表。我不确定这一限制现在是否仍然适用

我写了一个小测试程序,它可以连续分配和存储1GB的内存块。由于.NET似乎延迟了分配,我还用数据填充了块。我发现,一旦RAM用完,.NET就可以正确地分页到磁盘,程序速度明显变慢,但从未崩溃或OOM-ed


那么,为什么.NET似乎在处理许多小对象时遇到麻烦呢?这对我的配置来说是特殊的吗?

分页是操作系统的一项功能,所以这不是.NET做或不做的事情

OOM的一个常见来源是内存碎片。请记住,在托管应用程序中实际上并没有分配任何内容。您只需创建对象。运行时分配存储这些对象所需的内存。这些分配是在称为段的块中完成的。它们被分配为连续内存。碎片化可能导致没有足够的连续内存来执行新段的分配。如果无法分配段,则运行时抛出OOM

OOM的另一个常见来源是地址空间耗尽。一个常见的误解是,只要系统上有足够的可用内存,OOM就不会发生。32位应用程序并非如此。它们的地址空间为2GB或4GB(如果在64位和大内存地址感知上)。无论系统可能有多少内存,高于该值的任何内容都将触发OOM。由于您的问题标记为x64,我假设这是一个64位应用程序,在这种情况下,地址空间耗尽可能不是问题所在

就目前情况而言,您的问题确实包含了足够的信息来说明为什么会看到OOM异常。您是否将所有这些小对象存储在列表或其他结构中?如果是这样,您可能会使用非常大的数组,因为许多集合类都是使用数组实现的

以确认,.NET能够很好地分页到磁盘

为测试系统行为而不断分配RAM块的普通程序

分配将以1GB大小开始的块进行。人数 块是无限的。如果抛出OutOfMemory异常,则 尺寸将减小。每个区块都将填充数据,以确保其 内存页实际上是创建和初始化的

特别是在x64机箱上运行时,您应该能够观察到 NET可以很好地将可用的页面填充到磁盘上 物理内存

请注意,这很可能会严重降低您的系统速度, 可能会使流程web中其他正在运行的应用程序崩溃 浏览器为此臭名昭著


Windows正确地处理.NET的分页和任何其他进程。分页实际上不应该成为一个问题,因为Windows的工作是决定哪些页面可以保留在物理内存中,哪些页面可以分页到磁盘。但是,耗尽物理内存并不是一个好迹象,因为这意味着系统中的所有进程都需要频繁访问物理内存中不适合的页面

发生OOM还有其他原因:

32位计算机或WOW64下的64位计算机上运行的x86进程的进程地址空间不足。 基本上,默认情况下,该进程不能超过2GB。x86进程可以在32位机器上使用/3GB选项使用3GB,或者在WOW64下使用3GB,如果它们已标记为大地址感知

要了解它是以2GB、3GB还是4GB的速度运行,请使用Performance Monitor下的虚拟大小计数器,或者从Microsoft下载Process Explorer。我已经测试过几次了,它总是在198000KB的虚拟大小附近崩溃。请注意,任务管理器在Windows 7上仅具有提交大小,而这不如虚拟大小准确

内存碎片也可能是一个原因,但我不认为它适用于只有被垃圾收集器压缩的小对象的情况

资源耗尽 如果您的小对象使用不受管理的GDI句柄,默认情况下,您可能会用完大约10000个。在这种情况下,屏幕的一个或多个部分会出现OOM错误,并伴有红色X叉

提交大小包含所有已分配且正在使用的页面,而不考虑页面大小
在这一点上,d在RAM中或在RAM中。它表示进程当前对内存的需求。虚拟大小是完整的进程地址空间,其中包括提交和保留的段。后者是为将来使用而保留的占位符地址,但尚未使用或分配,甚至在分页文件中也未使用或分配。

您确定总共没有超过2GB的对象吗?限制不是列表可以有2GB的对象。这将是一个200万1kb对象的硬限制。尽管由于进程中所有其他对象的内存开销,您很可能远远低于这个数字。在程序上运行探查器,查看使用了多少对象和多少ram。将其设为64位进程,并查看进程的专用字节计数器。另外,请查看100%分配失败时的系统提交费用,以及实际使用情况大致指示分页开始发生的时间。这是一个64位进程。@usr我将检查该值。我没有明确说明,但该进程是64位的。我的印象是,内存碎片在64位应用程序中是不相关的,并且至少在几十年内不会发生耗尽。对象存储在一个非常类似于大型树的结构中。一个节点本身永远不会超过几千个连接。除了OOM,整个应用程序也会无限期地冻结。我在一小时后将其杀死。延迟很可能是由于GC超时工作造成的。我无法解释为什么会看到OOM,但可以使用WinDbg/SOS调查托管对象和分配的段。也许这可以给你一些线索。我没有意识到SOS,谢谢你的提示。供参考:您能在虚拟与提交大小之间展开一点吗?Mafu,添加了信息提交大小与虚拟大小。我希望有帮助。