c00*_*0fd 18 c# memory asp.net out-of-memory
我在我的开发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;
}
Run Code Online (Sandbox Code Playgroud)
我得到了System.OutOfMemoryException这一行:
ms.Write(buff, 0, nSz);
Run Code Online (Sandbox Code Playgroud)
分配268435456个字节时抛出:
Alloc size = 268435456
这是0x10000000或256 MB.所以我想知道是否需要设置一些全局设置才能使其正常工作?
以下是项目配置设置的屏幕截图:

Lan*_*kin 28
简答 - 开发服务器是32位进程.
"为什么只有256Mb?"的答案很长
首先,让我们了解它是如何工作的.
MemoryStream有内部byte []缓冲区来保存所有数据.它无法预测此缓冲区的确切大小,因此它只是用一些初始值初始化它.
位置和长度属性不反映实际的缓冲区大小 - 它们是反映写入的字节数的逻辑值,并且很容易小于实际的物理缓冲区大小.
当这个内部缓冲区不能适合所有数据时,它应该"重新调整大小",但在现实生活中它意味着创建两倍于前一个缓冲区大小的新缓冲区,然后将数据从旧缓冲区复制到新缓冲区.
因此,如果缓冲区的长度为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;
}
Run Code Online (Sandbox Code Playgroud)
如果它内置在x64/AnyCPU并从控制台运行 - 一切正常.
如果它是跨x86构建的 - 它在控制台中失败了.
如果你说它是内置x64的Page_Load,并从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位).
附注:
| 归档时间: |
|
| 查看次数: |
39858 次 |
| 最近记录: |