У меня есть ОЧЕНЬ большой текстовый файл для разбора (~ 2 ГБ). по разным причинам мне приходится обрабатывать файлы по очереди. Я делаю это, загружая текстовый файл в память (на сервере, на котором я запускаю синтаксический анализатор, есть достаточное количество памяти) с var records = Regex.Split(File.ReadAllText(dumpPath, Encoding.Default), @"my regex here").Where(s => !string.IsNullOrEmpty(s));
. это потребляет ОЗУ, эквивалентную размеру текстового файла плюс несколько МБ для служебных данных IEnumerable
. Все идет нормально. , затем я просматриваю коллекцию с foreach (var recordsd in records) {...}
Странное поведение синтаксического анализа большого текстового файла с использованием цикла foreach (C# .NET 4)
вот интересная деталь. Я делаю много строковых манипуляций и регулярных выражений в цикле foreach. то программа быстро бомбит с System.OutOfMemoryException, хотя я никогда не использую больше, чем несколько kB в цикле foreach. Я сделал несколько снимков памяти, используя профилировщик по своему выбору (профилировщик памяти ANTS), видя миллионы и миллионы строковых объектов Generation 2 в куче, потребляя всю доступную память.
видя, что я - только как тест - включал GC.Collect();
в конце каждого итерация, и вуаля, проблема не решена и не более из исключений памяти (конечно из-за постоянных коллекций мусора Программа теперь работает кропотливо медленно). Единственная потребляемая память - это размер фактического файла.
сейчас я не могу объяснить, почему это происходит и как его предотвратить. к моему пониманию, в тот самый момент, когда переменная выходит из сферы действия и не имеет больше (активных) ссылок на нее, должна быть отмечена для сбора мусора, не так ли?
с другой стороны записка, я попытался запустить программу на действительно массивной машине (64 ГБ оперативной памяти). программа завершилась успешно, но никогда не выпускала один байт памяти до ее закрытия. Зачем? если больше нет ссылок на объект плюс, если объект выходит из области видимости, почему память так и не была выпущена?
Не настоящий вопрос, почему строки заканчиваются в поколении 2? Вы должны как-то держаться за них достаточно долго, чтобы пропустить очищения gen0 и gen1. Замечание. Вы можете попытаться выполнить 'GC.Collect (2, GCCollectionMode.Optimized)', чтобы ускорить сбор. – adrianm