Очень большая загрузка данных вызывает исключение нехватки памяти в foreach - PullRequest
0 голосов
/ 30 января 2012

Прежде всего, я получил этот огромный XML-файл, который представляет данные, собранные оборудованием.Я превращаю это в объект.Фактически этот объект получил список объектов.Эти объекты имеют три строки в них.Строки выглядят так:

0,12987; 0,45678; ...

Это своего рода список двойников, упорядоченный таким образом для вопросоввыступления.В каждой строке 1k двойников, так что 3k по объектам, и есть что-то вроде объектов 3k, просто чтобы дать вам представление о типичном случае.

Когда я читаю данные, я больше всего получаю все двойники изобъекты и добавить их в тот же список.Я создал «объект, который содержит три двойника» (по одному для каждой строки) в foreach, я получаю все объекты и разбиваю свои строки на массивы.После этого я зацикливаюсь, чтобы превратить мои массивы в список «объектов, содержащих три двойки», и добавляю все это в один список, чтобы я мог использовать его для дальнейших операций.

Вызывает исключение нехватки памяти до конца.Идеи?Что-то с linq будет лучшим.

То, что я получил, выглядит так:

1 Ответ

3 голосов
/ 30 января 2012

Давайте сделаем немного математики. 1000 значений на строку * 8 символов на значение (6 цифр плюс запятая и точка с запятой) * 2 байта на символ * 3 строки на объект = 48 000 байтов на объект. Это само по себе не много, и даже с 3000 объектами мы все еще говорим о 150 МБ ОЗУ. Это все еще ничего для современной системы. Преобразование в двойные массивы еще меньше, поскольку вместо значения используется только 8 байтов. Строка также является ссылочным типом, поэтому в строковой версии для этого также потребовались бы дополнительные затраты. Важно то, что независимо от того, как вы играете в кости, у вас все еще не хватает порогового значения 85 000 байт, чтобы они застряли в куче больших объектов, нормальном источнике OutOfMemoryException.

Без кода трудно точно понять, что вы делаете, но у меня есть пара разных догадок:

  1. Многие значения в вашей строке содержат более 5 цифр, так что в конце концов вы пересекаете магический порог в 85 000 байт, и ваши объекты попадают в кучу больших объектов в сборщике мусора. Таким образом, они не собираются, и по мере того, как вы продолжаете обрабатывать объекты, вы вскоре исчерпываете себя из адресного пространства (не реального ОЗУ).
  2. Вы извлекаете свои двойники таким образом, что перестраиваете строку снова и снова. Это создает большую нагрузку на память для сборщика мусора, так как он заново создает строки снова и снова.
  3. Если это длительно работающая программа, в которой размер и количество элементов в каждой строке могут значительно различаться, возможно, со временем вы столкнетесь с несколькими большими списками больших значений, которые будут толкать ваш объект чуть более 85 000 байт.

В любом случае, то, что вы хотите здесь сделать, - это прекратить вещи с точки зрения списков и начать думать с точки зрения последовательностей. Вместо List<string> или List<double> попробуйте IEnumerable<string> и IEnumerable<double>. Напишите синтаксический анализатор для вашей строки, который использует ключевое слово yield, чтобы создать блок итератора, который будет извлекать дубликаты из вашей строки по одной, перебирая символы, не меняя строку. Это улучшит производительность way и, вероятно, также исправит проблему с памятью.

...