填充MemoryStream时OutOfMemoryException:在16GB系统上分配256MB

我在我的开发IIS服务器(来自VS2010 IDE)上运行以下方法,在64位Windows 7计算机上安装了16 GB RAM:

public static MemoryStream copyStreamIntoMemoryStream(Stream stream) { long uiLen = stream.Length; byte[] buff = new byte[0x8000]; int nSz; MemoryStream ms = new MemoryStream(); try { while ((nSz = stream.Read(buff, 0, buff.Length)) != 0) { ms.Write(buff, 0, nSz); } } finally { Debug.WriteLine("Alloc size=" + ms.Length); } return ms; } 

我在这一行得到System.OutOfMemoryException

 ms.Write(buff, 0, nSz); 

分配268435456个字节时抛出:

Alloc尺寸= 268435456

这是0x10000000或256 MB。 所以我想知道是否需要设置一些全局设置才能使其正常工作?

以下是项目配置设置的屏幕截图: 在此处输入图像描述

简答 – 开发服务器是32位进程。

“为什么只有256Mb?”的答案很长

首先,让我们了解它是如何工作的。

MemoryStream有内部byte []缓冲区来保存所有数据。 它无法预测此缓冲区的确切大小,因此它只是用一些初始值初始化它。

位置和长度属性不反映实际的缓冲区大小 – 它们是反映写入字节数的逻辑值,并且很容易小于实际的物理缓冲区大小。

当这个内部缓冲区不能适应所有数据时,它应该“重新resize”,但在现实生活中它意味着创建两倍于前一个缓冲区大小的新缓冲区 ,然后将数据从旧缓冲区复制到新缓冲区。

因此,如果缓冲区的长度为256Mb,并且您需要写入新数据,这意味着.Net需要找到另一个512Mb数据块 – 其余部分都已就绪,因此堆应该至少为768Mb收到OutOfMemory时的内存分配时刻。

另请注意,默认情况下.Net中没有单个对象(包括数组)的大小超过2Gb。

好的,所以这里是模拟正在发生的事情的样本:

  byte[] buf = new byte[32768 - 10]; for (; ; ) { long newSize = (long)buf.Length * 2; Console.WriteLine(newSize); if (newSize > int.MaxValue) { Console.WriteLine("Now we reach the max 2Gb per single object, stopping"); break; } var newbuf = new byte[newSize]; Array.Copy(buf, newbuf, buf.Length); buf = newbuf; } 

如果它内置在x64 / AnyCPU并从控制台运行 – 一切正常。

如果它是跨x86构建的 – 它在控制台中失败了。

如果你把它说成Page_Load,内置x64,并从VS.Net Web服务器打开 – 它就失败了。

如果你对IIS做同样的事情 – 一切都很好。

希望这可以帮助。

如果您使用的是默认的VS开发服务器,那么您将在x86 / 32位进程中运行代码。 如果您使用完整的IIS – 最有可能在IIS中,特定的AppPool配置为在x86(32位模式)下运行,因此地址空间非常有限(除非您将应用程序标记为大地址识别,否则为2GB)。

如果是IIS,请确保已配置应用程序轮询以运行x64(不确定什么是默认值)。 确保您的代码目标设置为AnyCPU或x64。

对于独立的C#应用​​程序 – 默认情况下,它们使用x86或AnyCPU / Prefer x86进行编译 – 将目标平台更改为x64。

要获得对IIS的x64支持,您可以从下载IIS 8.0 Express 安装完整的IIS或安装IIS Express 8.0(Windows 7附带的7.5仅为32位)。

附注:

  • 如果您刚刚安装了完整的IIS,请确保更新您的解决方案以使用IIS作为站点的主机。
  • 我没有机器检查是否需要使用x64支持IIS Express的任何其他步骤。 看看这个问题 – 无法让IIS Express 8测试版以64位进程运行网站 – 因为它可能会给你一些想法。
  • 您也可以尝试根据此处的建议构建自己的x64版本的开发服务器 – Visual Studio 2010 WebDev WebServer(Cassini)是否与64位兼容?