Уменьшение объема памяти, занимаемой большой незнакомой кодовой базой

Предположим, у вас есть довольно большое (~2,2 MLOC), довольно старое (начатое более 10 лет назад) настольное приложение Windows на C/C++. Около 10% модулей являются внешними и не имеют исходников, только символы отладки.

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


person Constantin    schedule 23.09.2008    source источник


Ответы (7)


Переопределите malloc()/free() и new()/delete() с помощью оболочек, которые отслеживают, насколько велики выделения и (записывая стек вызовов, а затем сопоставляя его с таблицей символов), откуда они сделаны. При выключении ваша оболочка отображает всю выделенную память.

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

person moonshadow    schedule 23.09.2008
comment
Можете ли вы рассказать о лучшем способе переопределения функций распределения для всего приложения, желательно с ограниченными изменениями исходного кода? Кроме того, есть много обработки COM/BSTR; я считаю, что их распределители не могут быть исключены из анализа. - person Constantin; 23.09.2008

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

person yrp    schedule 23.09.2008


Есть шанс, что вы сможете очень быстро найти существенные недостатки. Сначала вы должны проверить, для чего используется память. Я нашел очень удобным для этого инструмент Memory Validator.

Когда у вас есть эта «карта использования памяти», вы можете проверить наличие Low Hanging Fruit. Существуют ли какие-либо структуры данных, потребляющие много памяти, которые можно было бы представить в более компактной форме? Это часто возможно, особенно. когда доступ к данным хорошо инкапсулирован и когда у вас есть запасная мощность ЦП, вы можете посвятить их сжатию/распаковке при каждом доступе.

person Suma    schedule 23.09.2008
comment
Это зависит от того, имеет ли он в виду созданный 10 лет назад, неизменный с тех пор, или он органически рос и накапливал мусор в течение последних 10 лет. Вторая категория приложений определенно может потреблять много памяти. - person Brian; 23.09.2008
comment
Он растет. И накапливается. Требование снизить потребление ресурсов, как всегда, передается сверху. - person Constantin; 23.09.2008

Я не думаю, что ваш вопрос правильно поставлен.

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

Я бы посоветовал вам профилировать выполнение программы и внимательно изучить код.

person Remo.D    schedule 23.09.2008
comment
Размер исходного кода намекает на общую сложность проекта. Как вы думаете, сколько времени потребуется, чтобы внимательно изучить 400 KLOC? :) - person Constantin; 23.09.2008
comment
это должно быть легко. 400 КБ - это не то, что я бы назвал большим :), так как вам нужно только проверить распределение кучи, найти все вызовы malloc и новые вызовы, и вы почти у цели. - person gbjbaanb; 23.09.2008
comment
gbjbaanb, я хотел бы показать вам только график зависимостей модулей :) и что касается поиска всех malloc и новых, есть также по крайней мере SysAllocString (часто похороненный внутри CComBSTR) - person Constantin; 23.09.2008

Первыми местами, с которых я мог бы начать, были бы:

Выполняет ли приложение много предварительно выделенной памяти для последующего использования? Часто ли эта память лежит без дела, никогда не раздается? Рассмотрите возможность переключения на обновление/удаление (или лучше используйте smart_ptr) по мере необходимости.

Использует ли код статический массив, такой как

Object arrayOfObjs[MAX_THAT_WILL_EVER_BE_USED];

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

person Doug T.    schedule 23.09.2008

Одним из инструментов для анализа использования памяти является LeakDiag, доступный для бесплатной загрузки. от Майкрософт. По-видимому, это позволяет подключить все распределители пользовательского режима к VirtualAlloc и в любое время сбрасывать моментальные снимки распределения процессов в XML. Затем эти моментальные снимки можно использовать для определения того, какие стеки вызовов выделяют больше всего памяти и какие стеки вызовов имеют утечку. Ему не хватает красивого интерфейса для анализа моментальных снимков (если только вы не можете получить LDParser/LDGrapher через поддержку Microsoft Premier), но все данные есть.

Еще одна вещь, которую следует отметить, это то, что у вас могут быть ложные срабатывания от распределителя BSTR из-за кэширования, см. "Эй, почему я сливаю все свои BSTR?"

person Constantin    schedule 24.09.2008