1

Winforms アプリには、ローカル ファイル システム (またはネットワーク上の場所) から何千ものファイルを読み取り、それらをデータベースに格納するという要件があります。

ファイルをロードする最も効率的な方法は何でしょうか? 合計で数ギガバイトのデータが存在する可能性があります。

File.ReadAllBytesは現在使用されていますが、コンピューターのメモリが使い果たされると、アプリケーションは最終的にロックアップします。

現在のコードは、バイナリ データの読み取りに使用されるファイル パスを含むテーブルをループします。

protected CustomFile ConvertFile(string path)
{
    try
    {
        byte[] file = File.ReadAllBytes(path);
        return new CustomFile { FileValue = file };
    }
    catch
    {
        return null;
    }
}

データは、NHibernate を ORM として使用してデータベース (SQL Server 2008 R2 または 2012) に保存されます。

4

2 に答える 2

1

最初に、私の知識は NET 4.0 より前のものであることを述べさせてください。したがって、この分野で改善が行われることを知っているため、この情報は古くなっている可能性があります。

File.ReadAllBytesを使用して大きなファイル (85kb を超える) を読み取らないでください。特に、多数のファイルを順番に読み取っている場合はそうです。繰り返しますが、しないでください。

代わりにストリームやBinaryReader.Readのようなものを使用して、読み取りをバッファリングします。単一のバッファを介して CPU を爆発させないため、これは効率的ではないように聞こえるかもしれませんが、ReadAllBytes でそれを行うと、発見したように機能しません。

その理由は、ReadAllBytes がバイト配列内のすべてのものを読み取るためです。そのバイト配列がメモリ内で 85Kb を超える場合 (配列要素の数などの他の考慮事項があります)、ラージ オブジェクト ヒープに入りますが、これは問題ありませんが、LOH はメモリを移動せず、解放されたスペースを最適化することもありません。 、単純化すると、次のことが起こります。

  • 1GB のファイルを読み取り、LOH に 1GB のチャンクがあり、ファイルを保存します。(GC サイクルなし)
  • 1.5 GB のファイルを読み取り、1.5 GB のメモリ チャンクを要求すると、LOH の最後に移動しますが、GC サイクルが発生すると、以前に使用した 1 GB のチャンクがクリアされますが、現在は 2.5 GB のメモリのチャンクがあります。 、最初の 1 GB は無料です。
  • 1.6GB のファイルを読み込むと、最初の 1GB の空きブロックが機能しないため、アロケーターは最後まで進みます。これで、4.1GB のメモリ チャンクができました。
  • 繰り返す。

メモリが不足していますが、実際にはすべてを使用しているわけではありません。断片化が原因である可能性があります。また、ファイルが非常に大きい場合、実際に実際の OOM 状況に陥ることがあります (Windows 32 ビットのプロセス空間は 2GB だと思いますか?)。

ファイルが順序付けられていないか、相互に依存していない場合は、BinaryReader を使用してバッファリングすることでそれらを読み取るいくつかのスレッドでジョブが完了する可能性があります。

参考文献:

http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/learning-memory-management/memory-management-fundamentals

https://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/

于 2013-03-29T22:47:50.910 に答える
0

多くのファイルがある場合は、それらを 1 つずつ読み取る必要があります。

大きなファイルがあり、データベースで許可されている場合は、それらをブロックごとにバッファーに読み取り、ブロックごとにデータベースに書き込む必要があります。を使用すると、ファイルが大きすぎてランタイムのメモリに収まらない場合にエラーが発生するFile.ReadAllBytesことがあります。OutOfMemoryException上限は 2 GiB 未満で、アプリケーションをしばらく実行するとメモリが断片化される場合はさらに少なくなります。

于 2013-03-29T22:45:19.200 に答える