Не удается отследить источник огромного использования памяти - PullRequest
5 голосов
/ 15 июля 2011

Я пытался отследить проблему с памятью в течение нескольких дней - моя программа использует около 3 ГБ памяти, тогда как она должна использовать около 200–300 МБ. Valgrind фактически сообщает, что он использует ~ 300 МБ на пике, и не сообщает об утечках памяти.

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

  • Массив постоянного размера wchar_t (всего 4 МБ)
  • Карта между словами и списком связанных значений. Это растет с размером ввода. Если во входном файле содержится 1 000 000 уникальных слов, в дереве будет 1 000 000 записей.

Я делаю огромное количество выделений и освобождений (используя new и delete) - как минимум два на одно уникальное слово. Возможно ли, что свободная память по какой-то причине не используется повторно, из-за чего программа продолжает получать все больше и больше памяти? Он продолжает захватывать больше, продолжая бежать.

В общем, есть идеи о том, куда я должен идти отсюда?

Редактировать 1 (по совету Грэма): Один из путей, который я попробую, - это минимизация распределения. Я буду работать с одной строкой на поток (которая может иногда увеличиваться, если слово длиннее, чем эта строка), но если я правильно запомню свой код, это исключит огромное количество вызовов new / delete. Если все пойдет хорошо, у меня останутся: одноразовое распределение входного буфера, одноразовое выделение строки на поток (с некоторыми перераспределениями), два выделения на запись в карте (одно для ключа, одно для значения).

Спасибо!

Ответы [ 3 ]

7 голосов
/ 15 июля 2011

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

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

РЕДАКТИРОВАТЬ: вышеприведенное предложение предполагает, что выделяемые объекты std::string с. Если это не так, то вы, вероятно, все еще можете применить общую технику хранения старых пустых объектов для повторного использования.

0 голосов
/ 15 июля 2011

Вы должны попытаться обернуть распределение ресурсов в класс, если можете. Вызовите new в конструкторе и удалите в деструкторе. Попробуйте воспользоваться возможностями, чтобы управление памятью осуществлялось более автоматически.

http://en.wikipedia.org/wiki/RAII

0 голосов
/ 15 июля 2011

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

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

Это приложение для Windows?Как вы распределяете и освобождаете память?И как вы определяете, сколько памяти использует приложение?

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