Знай свою память


Очень часто бывает так, что какая-то программа занимает очень много места в памяти.
Например, не закрываешь Firefox час-другой и вот он уже 200-300Мб памяти отъел. Или запустил игру, а она уже на первом уровне занимает 1.5Гб.
Куда? Зачем? Надо ли этим программам столько памяти? Неизвестно.
Ответить на этот вопрос бывает непросто, даже если ты сам написал эту программу.
Но на самом деле можно очень легко проверить - нужно им столько памяти или нет.

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

Как это работает:

Есть в WinAPI такие замечательные функции, как EmptyWorkingSet и SetProcessWorkingSetSize. Они позволяют сказать запущенному процессу, чтобы он “освободил” всю используемую память. Точнее, не совсем “освободил”, а скорее, чтобы он выгрузил эту память из оперативной памяти куда-нибудь, чтобы освободить оперативную память для других процессов.
Я не хочу тут писать подробно про систему управления памятью в Windows, ибо это тема для отдельного поста, а то и нескольких.
Скажу только, что эти функции позволяют убрать из памяти неиспользуемые данные и сильно уменьшить Mem Usage у программ. А Mem Usage - это то, что вы видите в Windows Task Manager. То, что большинство пользователей считает реальным расходом памяти. Хотя на самом деле эти цифры в Task Manager не имеют никакого отношения к реальному расходу памяти. Вы можете выделить 1Гб памяти в своей программе, потом вызвать EmptyWorkingSet и Task Manager будет показывать, что ваша программа занимает всего 1-2 Мб в памяти. При этом выделенная память никуда не девается - она всё еще принадлежит процессу. Мало того, если памяти достаточно, то эти “выгруженные” области памяти на самом деле будут продолжать висеть в оперативной памяти и доступ к ним будет мгновенный. Если же памяти мало, то Windows может скинуть эти области в swap файл. Собственно, именно для этого эта фича и нужна - позволить Windows решать самой, какая память важна, а какая нет.

В итоге, самое простое применение этих функций - сокрытие реального использования памяти. Например, если вы пишете игру, то вызывайте эти функции каждый раз после инициализации нового уровня и ваш Mem Usage будет небольшим. Конечно, более менее опытный пользователь всё поймёт и найдет реальный расход памяти, но для 99% пользователей это прокатит - все будут думать, что игра занимает в памяти 100Мб, а не 300.

Но есть и более интересные методы применения этих функций. Я их использую для того, чтобы понять, сколько именно программе нужно памяти в каждый конкретный момент, сколько она РЕАЛЬНО использует памяти. А после этого можно уже искать, почему программа на самом деле использует в 3 раза больше памяти, чем ей надо.

Делаются такие исследования очень просто.
Надо вызвать EmptyWorkingSet перед вызовом какого-либо алгоритма (под алгоритмом я понимаю всё, что угодно - загрузка уровня в игре, открытие нового интерфейса, рассчет маршрута в навигационном оборудовании, поиск вируса по базе вирусов и т.п.).
Потом открыть Task Manager и замерить Mem Usage.
Потом запустить ваш алгоритм и замерить Mem Usage после того, как он отработает.
Увеличение Mem Usage - это и будет реальная память, которая нужна этому алгоритму.
Это всё верно потому, что Windows загрузит в Mem Usage только те страницы памяти, к которым реально произошло обращение. Всё остальное останется “выгруженным”.
Причём я проводил тесты - скорость работы с этой “выгруженной” памятью практически такая же, как и с той, что уже в Mem Usage. Разница в скорости измеряется в единицах процентов.

Но теория - теорией, а практика понятнее.
Для примера я выбрал игру Farm Frenzy (Весёлая ферма), т.к. она у меня установлена и пройдена.
Давайте попробуем немного исследовать её с моей тулзой.
Эта игра запускает 2 процесса farm.exe и farm.RWG. Так что для оптимизации памяти используем командную строку “OptimizeWS.exe farm” - так мы одной строкой оптимизируем оба процесса (описание командной строки есть на странице скачивания тулзы).
Игра запускается под обычным user аккаунтом, так что для OptimizeWS.exe тоже администраторских прав не требуется.

После загузки меню игра занимает около 40мб.
После старта загруженной игры из меню - уже 300мб.
После оптимизации (“OptimizeWS.exe farm”), игра стала занимать 50Мб и плавно за пару минут использование памяти выросло до 96Мб. Через полчаса игра занимала 120Мб памяти, хотя ничего нового на экране не появлялось - всё тот же один уровень, все та же графика и звуки.
Это может указывать на утечку памяти или на очень редкий доступ к каким-то ресурсам, которые не обязательно в этом случае держать в памяти. Например, если звук играется раз в несколько минут, то его можно загружать с диска и выгружать всегда. То же самое касается любой графики, которая видна редко.
Через полчаса игры я вышел в меню. Игра стала занимать 42 мб.
Вызвал “OptimizeWS.exe farm” - игра занимает 3мб.
Потом открывал разные окошки в меню (награды, разработчики, опции) и использование памяти выросло до 17 мб.
Одна из особенностей использования такой оптимизации памяти - я могу легко узнать после ее использования, сколько реально занимает в памяти какое-либо меню, так как при его открытии вырастает использование памяти. Причем, это именно точное число памяти, так как система загрузит в память ТОЛЬКО те куски памяти, которые были запрошены при открывании меню. Это тоже полезно иногда проверять, если вам интересно, сколько памяти у вас в программе занимает тот или иной модуль, интерфейс, алгоритм и т.п. - всё, что вы можете в любой момент запустить и завершить.
После вызова “OptimizeWS.exe farm” опять стало 3мб и когда второй раз заходил в те же окна - использование памяти выше 10мб не поднялось.
Из этого можно сделать второй вывод, что 7мб было выделено во время первой инициализации этих окон и осталось висеть неиспользованное. Такое часто случается, что при первой инициализации делает много работы и какие-то данные просто забываются или оставляются в надежде на будущее использование, но реально они никогда не используются. Отлавливайте такие данные и удаляйте их сразу. Даже если они понадобятся через полчаса - можно их загрузить снова.

Дальше я уже не стал копать. Думаю, и так направление мысли понятно.
Уверен, периодическое использование этой тулзы может помочь всем.

Понравилась статья? Подпишись на RSS!

Похожие записи:
Книги + программисты = деньги
Не будите спящего программиста
2 признака кода с душком: убей его и лови всё молча
Я умею программировать на С++!?

Рекомендую книги по этой теме:

8 комментариев к Знай свою память

Ответить

 

 

 

Вы можете использовать эти HTML тэги

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>