Управление памятью при загрузке огромных файлов XML - PullRequest
1 голос
/ 24 марта 2009

У нас есть приложение, которое импортирует объекты из XML. XML составляет около 15 ГБ. Приложение всегда начинает исчерпывать память. Мы пытались освободить память между операциями, но это привело к снижению производительности. т.е. для завершения операции импорта требуется больше времени. Загрузка процессора достигает 100%

Приложение написано на C ++.

Приведет ли частый вызов к free() к проблемам с производительностью?


Повышено из комментария OP: анализатор, используемый в expat, который является SAX-анализатором с очень маленькой занимаемой площадью и настраиваемым управлением памятью.

Ответы [ 9 ]

5 голосов
/ 24 марта 2009

Используйте SAX парсер вместо DOM парсер.

3 голосов
/ 24 марта 2009

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

2 голосов
/ 24 марта 2009

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

Я считаю, что free() иногда может быть дорогостоящим, но это, конечно, очень сильно зависит от реализации платформы.

Кроме того, вы мало говорите о продолжительности жизни загруженных объектов; если XML составляет 15 ГБ, сколько из этого остается для каждого «объекта», после того как разметка будет проанализирована и выброшена?

Разумно обрабатывать входной документ такого размера в потоковом режиме, то есть не пытаться использовать подход DOM, который загружает и создает все дерево синтаксического анализа XML сразу.

1 голос
/ 24 марта 2009

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

Недавно мы сделали это для встраиваемой системы, в основном из соображений производительности, но она также сэкономила много памяти.

Хитрость заключалась в том, чтобы выделить большой блок - немного больше, чем нам нужно (вы могли бы выделить цепочку блоков, если хотите) - и просто возвращать «текущий» указатель (увеличивая его с помощью allocSize округляется до максимального значения выравнивания 4 в нашем случае, каждый раз). Это сократило наши накладные расходы на выделение ресурсов с порядка 52-60 байтов до <= 3 байтов. Мы также игнорировали «бесплатные» вызовы до тех пор, пока не закончили разбор, а затем не освободили весь блок. </p>

Если вы достаточно умны в распределении кадров, вы можете сэкономить много места и времени. Возможно, вам не удастся пройти весь путь до 15 ГБ, но стоило бы посмотреть, сколько места у вас действительно наверху ... Мой опыт работы с системами на основе DOM заключается в том, что они используют тонны небольших ресурсов, каждый из которых имеет относительно высокий накладные расходы.

(Если у вас есть виртуальная память, большой «блок» может даже не сильно повредить, если ваш доступ в любой момент времени является локальным для страницы или трех в любом случае ...)

Очевидно, что в долгосрочной перспективе вам нужно сохранить память, которая вам действительно нужна, но «чистая память» анализатора становится намного более эффективной.

1 голос
/ 24 марта 2009

Если вы хотите минимизировать использование памяти, взгляните на Как читать данные XML из файла с помощью Visual C ++ .

0 голосов
/ 24 марта 2009

Я сам не пробовал, но вы слышали о XMLLite , есть MSDN artical , представляющий его. Он используется MS Office для внутреннего использования.

0 голосов
/ 24 марта 2009

Попробуйте найти способ профилировать ваш код.

Если у вас нет профилировщика, попробуйте организовать свою работу так, чтобы у вас было только несколько команд free () (вместо многих, которые вы предлагаете).

Очень часто приходится находить правильный баланс между потреблением памяти и эффективностью времени.

0 голосов
/ 24 марта 2009

Может быть, стоит сказать, профилировщик.

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

Если вы выделяете и освобождаете память для одних и тех же объектов, вы можете создать пул этого объекта и сделать выделение / освобождение один раз.

0 голосов
/ 24 марта 2009

Мы пытались освободить память между операциями, но это привело к снижению производительности.

Приводит ли частый вызов free () к проблемам с производительностью?

На основании предоставленных доказательств да.

Поскольку вы уже используете expat, SAX-парсер, что именно вы free используете? Если вы можете освободить его, почему вы в первую очередь зациклили его?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...