WindowsサービスでSystem.OutOfMemoryExceptionが発生する(毎回30-60分)。サービスの仕事は、サービスデータが共通のXMLデータフォーマットに洗い流されるデータファイルを含む6つのディレクトリをループすることです。.NETヒープで文字列オブジェクトがいっぱいになる - > OutOfMemoryException
これらの6つのフォルダにはそれぞれ5-10.000個のファイルが含まれているため、ファイルの総数は約45.000であり、その日の新しいファイルが追加されます。 1日に約1-2000の新しいファイルが追加されます。ファイルは4KBから500KBです。
各データファイルは、XElementオブジェクトを介して共通のXMLデータ形式に洗われます。
サービスでRedGates ANTS Memory Profilerを使用しましたが、最もメモリを使用しているオブジェクトは文字列(約90.000.000バイト)とXElement(約51.000.000バイト)です。
メモリプロファイラで、文字列オブジェクトを使用しているものをトレースすると、文字列オブジェクトを使用しているXElementオブジェクトがほとんど(93%)ということがわかります。
サーバーには6つのCPUと6GBのRAMがあるため、なぜOutOfMemoryExceptionが表示されているのか分かりません。プロセスのWindowsサービスを見ると、MAXのRAM使用量は1.2GBとなっています。
文字列オブジェクトがインターンテーブルに格納されているため、.NETガベージコレクタで文字列オブジェクトがクリアされないことがあります。これはエラーかもしれません、もしあれば、私はそれについて何ができますか?
以下のコードは、ファイルをループする方法を示しています。ご覧のとおり、私は一度に20ファイルを取ろうとしました。これはOutOfMemoryExceptionを数時間押し込むだけなので、サービスは30〜60分ではなく4〜5時間実行されます。
なぜ私はOutOfMemoryExceptionを実行できますか?
private static void CheckExistingImportFiles(object sender, System.Timers.ElapsedEventArgs e)
{
CheckTimer.Stop();
var dir = Directory.GetFiles(RawDataDirectory.FullName, "*.*", SearchOption.AllDirectories);
List<ManualResetEvent> doneEvents = new List<ManualResetEvent>();
int i = 0;
//int doNumberOfFiles = 20;
foreach (string existingFile in Directory.GetFiles(RawDataDirectory.FullName, "*.*", SearchOption.AllDirectories))
{
if (existingFile.EndsWith("ignored") || existingFile.EndsWith("error") || existingFile.EndsWith("importing"))
{
//if (DateTime.UtcNow.Subtract(File.GetCreationTimeUtc(existingFile)).TotalDays > 5)
// File.Delete(existingFile);
//continue;
}
StringBuilder fullFileName = new StringBuilder().Append(existingFile);
if (!fullFileName.ToString().ToLower().EndsWith("error") && !fullFileName.ToString().ToLower().EndsWith("ignored") && !fullFileName.ToString().ToLower().EndsWith("importing"))
{
File.Move(fullFileName.ToString(), fullFileName + ".importing");
fullFileName = fullFileName.Append(".importing");
ImportFileJob newJob = new ImportFileJob(fullFileName.ToString());
doneEvents.Add(new ManualResetEvent(false));
ThreadPool.QueueUserWorkItem(newJob.Run, doneEvents.ElementAt(i));
i++;
}
//if (i > doNumberOfFiles)
//{
// i = 0;
// doNumberOfFiles = 20;
// break;
//}
}
i = 0;
WaitHandle.WaitAll(doneEvents.ToArray());
CheckTimer.Start();
}
'ImportFileJob'とは何ですか?どのように実装されていますか? – Tigran
あなたの 'StringBuilder'の使用は冗長です。 IOWの利点はありません。 – leppie
ImportFileJobはデータファイルを取り、xlstスタイルシートを使用してデータファイルを共通XMLデータファイルに変換します。 – Poku