21

16GBのRAMがインストールされた64ビットのWindows7マシン上の開発IISサーバー(VS2010 IDEから)で次の方法を実行しています。

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バイトが割り当てられたときにスローされます。

割り当てサイズ=268435456

これは0x10000000または256MBです。それで、それを機能させるために設定する必要があるグローバル設定があるかどうか疑問に思っていますか?

プロジェクトの構成設定のスクリーンショットは次のとおりです。 ここに画像の説明を入力してください

4

2 に答える 2

32

簡単な答え-開発サーバーは32ビットプロセスです。

「なぜ256Mbだけなのか」に対する長い答え

まず、それがどのように機能するかを理解しましょう。

MemoryStreamには、すべてのデータを保持するための内部byte[]バッファーがあります。このバッファの正確なサイズを予測することはできないため、初期値で初期化するだけです。

PositionプロパティとLengthプロパティは、実際のバッファサイズを反映していません。これらは、書き込まれるバイト数を反映する論理値であり、実際の物理バッファサイズよりも簡単に小さい場合があります。

この内部バッファがすべてのデータに適合できない場合は、「サイズ変更」する必要がありますが、実際には、前のバッファの2倍のサイズの新しいバッファを作成し、古いバッファから新しいバッファにデータをコピーすることを意味します。

したがって、バッファの長さが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.NetWebサーバーから開くと失敗します。

IISでも同じことをすれば、すべて問題ありません。

お役に立てれば。

于 2013-03-24T10:02:59.000 に答える
6

デフォルトのVS開発サーバーを使用している場合は、x86/32ビットプロセスでコードを実行しています。完全なIISを使用している場合-ほとんどの場合、IISでは特定のAppPoolがx86(32ビットモード)で実行されるように構成されているため、アドレス空間が非常に制限されます(アプリケーションをラージアドレス対応としてマークしていない限り、2GB)。

IISの場合は、x64を実行するようにアプリのポーリングを構成していることを確認してください(デフォルトが何であるかはわかりません)。コードのターゲットがAnyCPUまたはx64に設定されていることを確認してください。

スタンドアロンC#アプリケーションの場合(デフォルトではx86またはAnyCPU / Prefer x86でコンパイルされます)、ターゲットプラットフォームをx64に変更します。

IISのx64サポートを取得するには、完全なIISをインストールするか、 IIS8.0ExpressのダウンロードからIISExpress8.0(Windows 7に付属の7.5は32ビットのみ)をインストールします。

サイドノート:

于 2013-03-24T04:14:25.960 に答える