Как избежать нехватки памяти в приложении с высоким потреблением памяти? C / C ++ - PullRequest
13 голосов
/ 12 апреля 2009

Я написал конвертер, который принимает XML-файлы openstreetmap и преобразует их в двоичный формат рендеринга, который обычно составляет около 10% от исходного размера. Размер входного файла обычно составляет 3 ГБ и больше. Входные файлы не загружаются в память все сразу, но передаются в виде точек и полисов, затем запускается bsp и файл выводится. В последнее время на больших файлах ему не хватает памяти и он умирает (у рассматриваемого есть 14 миллионов точек и 1 миллион полигонов). Обычно моя программа использует от 1 до 1,2 ГБ оперативной памяти, когда это происходит. Я пытался увеличить виртуальную память с 2 до 8 ГБ (на XP), но это изменение не произвело никакого эффекта. Кроме того, поскольку этот код является открытым исходным кодом, я бы хотел, чтобы он работал независимо от доступного RAM (хотя и медленнее), он работает на Windows, Linux и Mac.

Какие методы я могу использовать, чтобы избежать переполнения памяти? Обрабатывать данные в меньших подмножествах и затем объединять окончательные результаты? Используете мой тип обработчика виртуальной памяти? Есть другие идеи?

Ответы [ 15 ]

0 голосов
/ 24 ноября 2014

Это старый вопрос, но, поскольку я недавно сделал то же самое ...

Простого ответа нет. В идеальном мире вы бы использовали машину с огромным адресным пространством (т.е. 64-битным) и огромным объемом физической памяти. Одного огромного адресного пространства недостаточно, или оно будет просто повреждено. В этом случае проанализируйте файл XML в базе данных и, используя соответствующие запросы, извлеките то, что вам нужно. Вполне вероятно, что именно это делает сама OSM (я думаю, что мир составляет около 330 ГБ).

На самом деле я все еще использую XP 32bit из соображений целесообразности.

Это компромисс между пространством и скоростью. Вы можете делать что угодно в любом объеме памяти, если вам все равно, сколько времени это займет. Используя структуры STL, вы можете анализировать все, что захотите, но скоро вам не хватит памяти. Вы можете определить свои собственные распределители, которые меняются местами, но опять же, это будет неэффективно, потому что карты, векторы, наборы и т. Д. Действительно не знают, что вы делаете.

Единственный способ, с помощью которого я нашел все это на небольшом месте на 32-битной машине, - это очень тщательно подумать о том, что я делаю, и о том, что нужно сделать, и разбить задачу на куски. Эффективное использование памяти (никогда не использует более ~ 100 МБ), но не очень быстро, но тогда это не имеет значения - как часто нужно анализировать данные XML?

0 голосов
/ 26 января 2011

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

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

0 голосов
/ 13 апреля 2009

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

Вот несколько вещей, которые вы можете сделать, чтобы помочь в этой ситуации:

  • Если вы работаете в Windows, используйте File Maps ( пример кода ). Это даст доступ к файлу через один указатель буфера, как будто вы читаете весь файл в памяти, только фактически не делая этого. Последние версии ядра Linux имеют похожий механизм.
  • Если вы можете, и похоже, что могли бы, сканируйте файл последовательно и избегайте создания DOM в памяти. Это значительно уменьшит время загрузки и требования к памяти.
  • Используйте пул памяти! У вас, вероятно, будет много крошечных объектов, таких как узлы, точки и еще много чего. Используйте пул памяти, чтобы выручить (я предполагаю, что вы используете неуправляемый язык. Поиск пула выделения и пулов памяти).
  • Если вы используете управляемый язык, по крайней мере переместите эту конкретную часть на неуправляемый язык и возьмите под контроль память и чтение файлов. Управляемые языки имеют нетривиальные накладные расходы, как по объему памяти, так и по производительности. (Да, я знаю, что это помечено "C ++" ...)
  • Попытка разработать алгоритм на месте, в котором вы одновременно считываете и обрабатываете только минимальный объем данных, поэтому ваши требования к памяти будут снижаться.

Наконец, позвольте мне указать, что сложные задачи требуют сложных мер. Если вы считаете, что можете себе позволить 64-разрядную машину с 8 ГБ ОЗУ, просто используйте алгоритм «чтение файла в память, обработка данных, запись вывода», даже если для его завершения требуется день.

0 голосов
/ 12 апреля 2009

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

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

Теперь это звучит просто, не так ли? (Рад, что я не обязан это делать :))

0 голосов
/ 12 апреля 2009

Звучит так, как будто вы используете txt для бинарного разговора, так зачем вам хранить все данные в памяти?
Разве вы не можете просто прочитать примитив из txt (xml) и сохранить его в двоичном потоке?

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