1

WCF サービスで BufferManager を使用しています。IDisposable を実装する BufferManager をラップする独自のクラスを作成しました。現在、私の Dispose メソッドは次のようになっています。

public void Dispose()
    {
        this.bufferManager.Clear();
    }

私の質問:これは、マネージャーによって取得されたすべてのバッファーで ReturnBuffer を呼び出すのと同じことを達成しますか?

背景として: 次のメソッドで BufferManager を使用しています。

public byte[] ReadAllBufferedBytes(string filePath)
    {
        using (var fileStream =
            new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            byte[] buffer = this.bufferManager.TakeBuffer((int)fileStream.Length);

            fileStream.Read(buffer, 0, buffer.Length);

            return buffer;
        }
    }

私がこれを行っている理由は、サービスを破壊する OutOfMemory 例外を取得し続けたためです。

ホスト サーバーには 3 GB のメモリがあります。サービスは InstanceContextMode.Single モードであるため、画像は一度に 1 つずつ処理されます。画像はバイト配列として受信されます - 最大のものは 100MB かもしれませんが、通常ははるかに小さくなります - 変換され、バイト配列として返されます。多くのものがラージ オブジェクト ヒープに置かれ、画像のサイズはかなり異なります。

問題がヒープの断片化であるかどうか疑問に思っています。

ドキュメントの各ページが変換されると、ディスク上の一時ファイルに追加されます。変換後、変換されたファイル全体をディスクからバイト配列に読み取り、それをクライアントに返します。

標準の File.ReadAllBytes メソッドは、ファイルから読み取るときに新しいバイト配列を作成します。これは、作業している画像サイズのために必然的に LOH になります (これが起こると思います)。ReadAllBufferedBytes メソッドを作成して同じことを行いましたが、バイト配列をバッファリングし、BufferManager が破棄されたときにバッファを返せるようにしました。

もう 1 つの質問は、これをすべて行う必要があるかどうかです。

4

1 に答える 1

0

BufferManager は通常、GC プレッシャーを防ぐ必要があるシナリオで使用されます。たとえば、非常に低いレベル (ソケットなど) でデータを送受信する場合など、小さな割り当てが多数ある場合です。byte[]ここでは多くのことが強調されていますが、それ以外の場合は、GC がメモリ割り当てを問題なく処理できるはずです。

変換されたドキュメント ファイル全体がメモリに読み込まれないようにするには、可能であれば、ストリーミングされた (応答) TransferModeと組み合わせて、FileStream を直接 (メモリにコンテンツ全体を読み込まずに - byte[]) 使用する必要があります。

于 2013-02-03T00:10:35.007 に答える