2009-03-24 3 views
1

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

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

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


Повышен с комментария ОРОМ: синтаксический анализатор используется в эмигранте, который является SAX парсер с очень небольшим размером, и настраиваемое управлением памятью.

+0

Какой парсер вы используете. MSXML? – Naveen

+0

Это один 15GB XML-файл? Сколько места вам ожидают результирующие объекты? Вы импортируете все объекты или только выделение? Вы на 64-битной платформе? –

+0

да Я на 64-битной платформе. Его единственный файл размером 15 ГБ. –

ответ

3

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

+0

Также - он должен использовать valgrind с массивом, чтобы посмотреть, какие классы являются лучшими кандидатами. –

2

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

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

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

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

0

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

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

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

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

+0

На самом деле было использовано memcpy (x, y, len). Поэтому мы решили освободить (y) после операции memcpy. Также мы попытались использовать memmove вместо memcpy –

+0

, что именно вы освобождаете? единственное, что я знаю в xpat, - это копирование значений из атрибутов или символьных данных, в каком случае y управляется парсером, а x - это то, что вы копируете, поэтому ни в одном случае вы не освободите x или y , –

0

Возможно, это должно сказать профайлер.

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

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

0

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

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

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

1

Если вы хотите свести к минимуму использование памяти, взгляните на How to read the XML data from a file by using Visual C++.

+0

Есть ли у вас какие-либо доказательства того, что импорт .net-инфраструктуры будет чистым преимуществом с использованием Expat, который имеет небольшой объем памяти? –

+0

@Pete Kirkham: Извините, не знаю. Я только прочитал бит Expat после ответа. –

0

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

1

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

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

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

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

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

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

+0

Является ли синтаксический анализатор expat внутренне выделять небольшие куски памяти, а затем выпускать его? У меня есть виртуальная память объемом 2 ГБ. Насколько большой размер блока будет достаточно справедливым? –

+0

Я не уверен насчет экспатов, особенно в режиме SAX.Самое простое, что нужно сделать, это переопределить распределитель, чтобы распечатать то, что он выделяет и освобождает, а затем проанализировать небольшую страницу. (Или собирайте статистику, а затем распечатайте их.) После того, как вы получите эту информацию, вы сможете принимать разумные решения о блоках. – leander