当RAM在C#中结束时会发生什么?

时间:2011-05-14 13:30:12

标签: c# .net memory-management virtual-memory

我不是计算机专家,所以让我试着更具体地提出这个问题:

我做了一些科学计算,计算有时需要大量内存来存储结果。几天前,我的输出文件占用了4 GB的硬盘,但我有这么多的RAM。所以:

  • 当您运行的程序分配的内存多于计算机中可用的内存时,CLR(或其他内容?)如何处理内存?它是否在HD中创建了一些交换? (我知道这可能会减慢我的程序,但我只对内存问题感兴趣)
  • 是否依赖于操作系统,比如我是在Linux上使用MONO还是在Windows上使用VS?

提前致谢!

3 个答案:

答案 0 :(得分:11)

我认为有用的方法是:内存是磁盘空间。 RAM 是一个快速缓存。我认为“当我有可用的RAM时,系统会将我的磁盘存储器移入其中”,而不是“当我没有RAM时,系统会将其交换到磁盘”。

这与大多数人对此的看法相反,但我发现它有所帮助。 RAM只是一种性能优化;您可以分配多少内存的实际限制是可用磁盘空间。

当然比这更复杂。在32位操作系统上,每个进程都有一个20亿字节的用户地址空间。 (对于内核地址空间也是如此,但让我们忽略它。)你可以访问的每一页内存,无论是在RAM中还是在磁盘上,都必须在该地址空间中。你可以分配超过20亿个字节,没问题。但是你一次只能处理2 GB的内容。如果分配了10 GB,则至少8 GB不会映射到地址空间。在这种情况下,您必须取消映射其他内容,然后将您想要的内容映射到地址空间以便获取它。

此外,很多事情都需要在连续的地址空间中。例如,如果您有1MB的堆栈,那么地址空间中需要有一百万个连续的字节。

当人们“内存不足”时,他们没有用完RAM; RAM只是磁盘上的快速缓存。它们没有耗尽磁盘空间;有很多。他们几乎总是处于没有足够的连续地址空间来满足需求的情况。

CLR内存管理器不会为您实现这些精美的map-and-unmap策略;基本上,你得到2GB的地址空间,就是这样。如果你想做一些花哨的事情,比如内存映射文件,你可以自己编写代码来管理内存。

答案 1 :(得分:3)

如果您分配的内存超过物理存在,是的,将使用交换空间。

如果分配的内存多于可寻址的内存,则会出现OutOfMemoryException

不确定Mono,但我猜这是依赖于运行时的,并且表现方式几乎相同(没有足够的物理内存会导致交换,分配太多会导致异常)。

答案 2 :(得分:3)

运行时只是要求操作系统获得更多内存。操作系统处理将内存的现有内容分页到磁盘,并在必要时交换内容以创建更多的空闲物理内存。对于托管的C#/ .NET程序,同样的事情发生在普通的非托管程序中。

托管应用程序世界的唯一区别是.NET运行时会产生一些内存开销,从而限制了应用程序实际可用的内存总量。例如,垃圾收集器需要一些内存空间来完成它的工作。

所以是的,它依赖于操作系统,至少在某种程度上如此。但是,大多数现代操作系统都有类似的内存管理方法。