2011-01-13 57 views
2

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

感谢您的帮助!

+0

它仍然限于分页文件的最大大小。在达到可寻址内存限制之前,您会达到这个目标。 – 2011-01-13 17:20:25

回答

4

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

+0

+1。很好的答案,很好的联系。 – David 2011-01-13 16:01:27

1

有什么可以从理论上解决。

你有什么样的物理知识,你是否超过了开始使用swap的速度,而swap通常仅限于某些选定磁盘分区的大小。

作为一个经验法则,一个物理内存的倍数往往会有少量(如一个或两个)为交换。

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

4

另一种可能性是程序试图分配一个大于2GB的内存块,这是一个.NET限制。添加的东西集合时就会发生这种情况(最常见的是DictionaryHashSet,也List或自动增加任何其他集合。)

DictionaryHashSet做到这一点的时候,如果你试图把超过约收集4700万件物品。虽然该集合可以容纳大约89.5百万个,但是增加集合的算法通过加倍来实现。如果您从一个空的Dictionary开始并开始添加项目,该收藏会翻倍,直到达到约4700万。然后它再次尝试翻倍并投掷OutOfMemoryException

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

+0

预先分配集合,使其容量足够大,以容纳您期望放入其中的许多项目。你能告诉我如何在HashSet的情况下做到这一点,即预分配?我可以在列表中做到这一点,但是对于HashSet呢? – 2011-12-27 06:54:48