3

ファイルをバイト [] データ パケットのストリームとして受信しています (合計サイズは事前にわかりません)。受信直後に処理する前にどこかに保存する必要があります (その場で処理を行うことはできません)。 )。受信したファイルの合計サイズは、10 KB から 4 GB 以上までさまざまです。

  • 受信したデータを格納するための 1 つのオプションは、 を使用することMemoryStreamです。つまり、一連のMemoryStream.Write(bufferReceived, 0, count)呼び出しを使用して、受信したパケットを格納します。これは非常に単純ですが、大きなファイルではメモリ不足の例外が発生することは明らかです。
  • 別のオプションは、を使用することFileStreamですFileStream.Write(bufferReceived, 0, count)。このようにして、メモリ不足の例外は発生しませんが、ディスク書き込みによるパフォーマンスの低下がよくわかりません (十分なメモリがまだ利用可能である限り、これは発生したくありません)。ディスクへのアクセスはできるだけ避けてください。しかし、これを制御する方法がわかりません。

MemoryStream.Write()私はいくつかのテストを行いましたが、ほとんどの場合、 vsの 10 000 回の連続呼び出しの間にパフォーマンスの違いはほとんどないようですFileStream.Write()が、多くはバッファサイズと問題のデータの総量 (つまり、書き込み数) に依存しているようです。 . 明らかに、MemoryStreamサイズの再割り当ても要因です。

  1. MemoryStreamとの組み合わせを使用することは理にかなっていますか。FileStreamつまり、デフォルトでメモリ ストリームに書き込みますが、受信したデータの合計量が 500 MB を超えると、それをFileStream;に書き込みます。次に、受信したデータを処理するために両方のストリームからチャンクを読み取ります (最初に から 500 MB を処理しMemoryStream、破棄してから から読み取りますFileStream)。

  2. もう 1 つの解決策は、内部配列の割り当てに連続したアドレス空間を必要としないカスタム メモリ ストリームの実装 (つまり、メモリ ストリームのリンク リスト) を使用することです。このようにして、少なくとも 64 ビット環境では、メモリ不足の例外が問題になることはなくなります。短所:余分な作業、ミスの余地が増える。

FileStreamでは、ディスク アクセスとメモリ キャッシング、つまりデータ サイズとパフォーマンスのバランスに関して、対MemoryStream読み取り/書き込みはどのように動作するのでしょうか。とにかく、十分なRAMが利用可能である限り、FileStreamメモリ(キャッシュ)から内部的に読み書きし、残りは仮想メモリが処理することを期待しています。FileStreamしかし、書き込み時に明示的にディスクにアクセスする頻度はわかりません。

どんな助けでも大歓迎です。

4

3 に答える 3

5

いいえ、これを最適化しようとしても意味がありません。Windows 自体は既にファイル書き込みをキャッシュしており、ファイル システム キャッシュによってバッファリングされています。したがって、テストはほぼ正確です。MemoryStream.Write() と FileStream.Write() の両方が実際に RAM に書き込み、パフォーマンスに大きな違いはありません。ファイル システム ドライバーは、バックグラウンドで遅延してディスクに書き込みます。

ファイル システム キャッシュに使用される RAM は、プロセスが必要な RAM を要求した後に残ったものです。MemoryStream を使用すると、ファイル システム キャッシュの効果が低下します。言い換えれば、一方をもう一方と交換しても、利益はありません。実際には、さらに悪いことに、RAM の使用量が2 倍になります。

これは、オペレーティング システム内ですでに大幅に最適化されています。

于 2013-10-30T16:50:20.287 に答える
3

バッファー サイズを定義できるFileStream コンストラクターを使用します。例えば:

using (outputFile = new FileStream("filename", 
    FileMode.Create, FileAccess.Write, FileShare.None, 65536))
{
}

デフォルトのバッファ サイズは 4K です。64K バッファーを使用すると、ファイル システムへの呼び出しの数が減ります。バッファーを大きくすると、書き込み回数が減りますが、各書き込みに時間がかかり始めます。経験的データ (このようなものを長年使用してきた) は、64K が非常に良い選択であることを示しています。

他の誰かが指摘したように、ファイル システムはさらにキャッシュを行い、バックグラウンドで実際のディスク書き込みを行う可能性があります。に書き込むよりも速くデータを受け取る可能性はほとんどありませんFileStream

于 2013-10-30T16:39:15.867 に答える
3

最近のバージョンの Windows ではデフォルトで書き込みキャッシュFileStreamが有効になっているため、物理ハード ドライブに実際に何かが書き込まれるタイミングや場合に Windows を使用して管理させることができると思います。

これらのファイルを受け取った後も残っていない場合は、ファイルを一時ディレクトリに書き込んで、使い終わったら削除する必要があります。

于 2013-10-30T15:51:22.877 に答える