2012-04-18 2 views
2

У меня есть ОЧЕНЬ большой текстовый файл для разбора (~ 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 ГБ оперативной памяти). программа завершилась успешно, но никогда не выпускала один байт памяти до ее закрытия. Зачем? если больше нет ссылок на объект плюс, если объект выходит из области видимости, почему память так и не была выпущена?

+1

Не настоящий вопрос, почему строки заканчиваются в поколении 2? Вы должны как-то держаться за них достаточно долго, чтобы пропустить очищения gen0 и gen1. Замечание. Вы можете попытаться выполнить 'GC.Collect (2, GCCollectionMode.Optimized)', чтобы ускорить сбор. – adrianm

ответ

5

сейчас я не могу объяснить, почему это происходит и как его предотвратить. к моему пониманию, в тот самый момент, когда переменная выходит из сферы действия и не имеет больше (активных) ссылок на нее, должна быть отмечена для сбора мусора, не так ли?

Нет. Там нет такого понятия, как «с пометкой» для сбора мусора, а переменных не являются мусор: объекты. И объект, который уже находится в gen2, не будет собираться мусором до следующего раза, когда GC смотрит на gen2, что относительно редко.

по различным причинам я должен обработать файл по очереди.

Затем вы получите ответ: используйте File.ReadLines, если вы используете .NET 4, и напишите эквивалент (это легко), если вы этого не сделаете. Тогда вам не нужен весь файл в памяти за один раз - всего одна строка. Использование памяти должно резко упасть. (Обратите внимание, что это ReadLines, неReadAllLines - последний будет читать весь файл в массив строк, которые не то, что вы хотите.)

на другой стороне записки, я попытался запустить программу на действительно массивной машине (64 ГБ ОЗУ). программа завершилась успешно, но никогда не выпускала один байт памяти до ее закрытия. Зачем?

Если вы говорите о памяти, что процесс занимает от операционной системы, я не верю что CLR всегда освобождает память. Я предполагаю, что он использует подход, который, если вы однажды использовали столько памяти, вы, вероятно, снова воспользуетесь этим.

+0

ok Я, вероятно, набрал слишком быстро и не перечитывал то, что я на самом деле писал. поэтому по различным другим причинам мне нужен весь текстовый файл в памяти, потому что я также делаю много случайного доступа к текстовому файлу. Кроме того, я просто хотел объяснить, что я вижу. Благодарю. – lightxx

+0

просто немного разбираться. файл генерируется устройством выборки ДНК с довольно загадочным файловым форматом. некоторые образцы ДНК распространяются более чем на одну линию, другие - нет. интерпретация значений, найденных в одной строке, зависит от значений, найденных в других строках. и так далее. цель состоит в том, чтобы преобразовать этот огромный текстовый файл в коллекцию настраиваемых объектов, которые анализируются и сохраняются в БД. это немного сложно объяснить все это, но важно увидеть файл в целом, разбирая его. все, что мне нужно знать, - это вызов вызова GC.Collect(); кажется, решает проблему, и что с этим связано. – lightxx

+0

Я действительно хочу, чтобы ваш комментарий был замечен, но мой представитель слишком низок :( – lightxx

Смежные вопросы