TextWriter/StreamWriter высокое использование памяти
У меня есть консольное приложение, которое читает большой текстовый файл с 40k+ строками, каждая строка - это ключ, который я использую при поиске, результаты которого записываются в выходной файл. Проблема в том, что я оставляю это консольное приложение работающим некоторое время, пока оно внезапно не закрывается, и я понимаю, что использование памяти процессами было очень высоким, оно было на уровне 1,6 ГБ, когда я в последний раз видел его сбой.
Я посмотрел вокруг и не нашел много ответов, я пытался использовать gcAllowVeryLargeObjects, но похоже, что я просто уклоняюсь от проблемы.
Ниже приведен фрагмент из моего main(), где я записываю в файл. Я не могу понять, почему использование памяти становится таким высоким. Я очищаю писателя после каждой записи (это может быть потому, что я держу файл открытым в течение такого длительного периода времени?).
TextWriter writer = new StreamWriter("output.csv", false));
foreach (var item in list)
{
Console.WriteLine("{0}/{1}", count, numofitem);
var result = TableServiceContext.Read(p.id);
if (result != null)
{
writer.WriteLine(String.Join(",", result.id,
result.code,
result.hash));
}
count++;
writer.Flush();
}
writer.Close();
Изменить: у меня есть 32 ГБ оперативной памяти на моем компьютере, поэтому я уверен, что он не хватает памяти, потому что мне не хватает оперативной памяти.
Edit2: изменил имя хранилища, поскольку это вводило в заблуждение.
2 ответа
Если средняя длина строки составляет 1 КБ, то 40 КБ строк - это 40 МБ, и это ничего. Поэтому я уверен, что проблема в вашем классе репозитория. Если это EF-репозиторий, попробуйте воссоздать DbContext для каждой строки.
Если вы хотите настроить свою программу, то вы можете использовать следующий метод: попробуйте поставить метки времени на вывод консоли, вы можете использовать класс секундомера и пытаться воссоздавать свой репозиторий каждые 10, 100 или N строк. Затем, глядя на временные метки, вы можете найти оптимальный N для использования.
var timer = Stopwatch.StartNew();
...
Console.WriteLine(timer.ElapsedMilliseconds);
Глядя на код, я думаю, что проблема не в Streamwriter, а в некоторой утечке памяти в вашем хранилище. Предложения для проверки:
- замените репозиторий каким-нибудь фиктивным, например, классом dummy_repository с тремя свойствами: id, value, hash.
- аналогичным образом создайте длинный "список", например, 40 тыс. небольших записей.
- запустите вашу программу и посмотрите, будет ли она по-прежнему потреблять память (я уверен, что она не будет)
- затем шаг за шагом добавьте обратно свои оригинальные детали. Посмотрите, какой шаг вызывает утечку памяти.