虚拟和物理内存/ OutOfMemoryException

时间:2011-01-13 15:46:38

标签: c# clr memory-management out-of-memory

我正在开发一个64位.Net Windows服务应用程序,它实际上会加载一堆数据进行处理。在执行数据量测试时,我们能够压倒该进程并抛出OutOfMemoryException(当它失败时,我没有关于进程的任何性能统计信息。)我很难相信进程请求了一大块内存自从在64位计算机上运行以来,已超出该进程的允许地址空间。我知道该进程正在一台机器上运行,该机器一直在80%-90%的物理内存使用率附近。我的问题是:如果机器的可用物理内存严重不足,CLR是否会抛出OutOfMemoryException,即使该进程不会超过其允许的虚拟内存量?

感谢您的帮助!

3 个答案:

答案 0 :(得分:4)

在64位环境中仍然存在一些可达限制。检查一下this page中最常见的一些。简而言之,是的,如果您的程序将高达128GB的数据加载到虚拟内存中,您仍然可能会耗尽内存。如果您没有设置IMAGE_FILE_LARGE_ADDRESS_AWARE环境变量,您仍然可能受到每个进程限制2GB的限制。

答案 1 :(得分:4)

另一种可能性是该程序试图分配一个大于2千兆字节的内存块,这是一个.NET限制。在向集合中添加内容时(通常是DictionaryHashSet,以及List或自动增长的任何其他集合,都会发生这种情况。)

DictionaryHashSet经常这样做,如果你试图将超过4700万件物品放入集合中。尽管该集合可以容纳大约8950万,但是增加集合的算法通过加倍来实现。如果您从空Dictionary开始并开始添加项目,则该集合会翻倍,直到达到大约4700万。然后它尝试再次加倍并抛出OutOfMemoryException

避免异常的方法是预先分配集合,使其容量足够大,以容纳您希望放入其中的许多项目。

答案 2 :(得分:1)

理论上你可以解决这个问题。

你有什么物理存在,当你超过开始使用swap时,通常只限于某些选择的磁盘分区的大小。

根据经验,一个物理内存的倍数倾向于少量(如一个或两个)作为交换。

所以是的,很可能你没有可用,而不是可寻址的内存。