解析するテキストファイルが非常に大きい(〜2GB)。いろいろな理由から私はファイルを行ごとに処理する必要があります。私はvar records = Regex.Split(File.ReadAllText(dumpPath, Encoding.Default), @"my regex here").Where(s => !string.IsNullOrEmpty(s));
でテキストファイルをメモリにロードすることで(パーサに十分なメモリがあるサーバーをロードしています)これは、テキストファイルのサイズに相当するRAMと、IEnumerable
のオーバーヘッドのための数MBを消費します。ここまでは順調ですね。 その後、私はforeach (var recordsd in records) {...}
foreachループを使用して大きなテキストファイルを解析する奇妙な動作(C#.NET 4)
とここで興味深い部分が来てコレクションを行きます。私はforeachループで文字列操作と正規表現をたくさん行います。 foreachループで数kB以上を使用することはありませんが、プログラムはSystem.OutOfMemoryExceptionで素早く爆撃します。 私の選択したプロファイラ(ANTSメモリプロファイラ)を使用していくつかのメモリスナップショットを作成し、ヒープ上の何百万も何百万という第2世代の文字列オブジェクトを見て、使用可能なメモリをすべて消費しました。それを見て
は、I - 単なるテストとしては、 - 各foreachの反復の終わりにGC.Collect();
を含め、出来上がり、問題は永久的なガベージコレクションプログラムの案の定(解決しないとメモリの例外のうち、それ以上今は辛抱強く遅く走る)。消費される唯一のメモリは、実際のファイルのサイズです。
今、なぜこのようなことが起こり、どのように防止するのか説明できません。私の理解には、変数が有効範囲外になり、もはやガベージコレクションのマークが付いた(アクティブな)参照がなくなってしまったのでしょうか?
別のメモでは、私は本当に大規模なマシン(64GBのRAM)でプログラムを実行しようとしました。プログラムは正常に終了しましたが、閉じられる前に1バイトのメモリが解放されませんでした。どうして?オブジェクトへの参照がなくなり、オブジェクトが有効範囲外になった場合、メモリが解放されないのはなぜですか?
ここ2世代で文字列が終わるのは本当ですか? gen0クリーンアップとgen1クリーンアップの両方を見逃してしまっても、どうにかしてそれらを保持しなければなりません。サイドノート。 'GC.Collect(2、GCCollectionMode.Optimized)'を実行すると、コレクションを高速化できます。 – adrianm