Уверен, не один я, размещая виртуалки с Windows 2008 и более свежими версиями на VMWare 4.x или 5.x, сталкивался с ситуацией, когда вроде сервер ничем особым не загружен, а память вся сожрана процентов на 90, а то и больше. И чего не делай, память он назад не отдает И я сейчас пишу не про общеизвестную ситуацию, когда горе-админы видят в Task Manager, что Memory free = 0 и поднимают страшный крик, что алчный Microsoft украл всю память, а про тот тяжелый случай, когда Task Manager показывает, что используется 90% RAM, но при этом сумма блоков, выделенных запущенным процессам, даже близка не равна этой величине. Если и вы находитесь в такой ситуации, приглашаю читать дальше.
Итак, запускаете вы в один прекрасный день Task Manager и видите там вот такую картину:
Кто сожрал память и почему непонятно, пытаемся увеличить глубину понимания при помощи Resource Monitor:
Что-то легче и понятнее не становиться, очень похоже на утечку, но это не утечка. А когда у нас происходит что-то неведомое и непонятное, мы зовем на помощь Марка Руссиновича, точнее его утилиту RamMap (у истинных профессионалов она есть, остальные качают ее по приведенной ссылке). Утиль, попыхтев, показывает нам следующую картину:
Вариантов картины может быть два. Первый виден на скриншоте — всю память пожрал какой-то драйвер. Второй вариант — вся память будет в блоке Metafile (встречается реже и обычно на серверах с неболее чем 4 ГБ памяти). Сначала поговорим про второй, как более простой и безысходный. Metafile — это кэш структур NTFS, в частности MFT. Т.к. один файл занимает примерно 1 Кб памяти, на серверах, где множество файлов, к которым постоянно идут какие-то обращения, кэш NTFS будет занимать немало места. Отключить его или как-то им управлять нельзя, можно только добавить RAM и смириться. Подробнее про то, как работает NTFS, можно почитать здесь.
Теперь про первый случай. Что ж это за драйвер такой, который все сожрал? Ответ можно найти в этом документе. Называется этот драйвер VMware Server Memory Controller и отвечает он в том числе и за функцию memory ballooning. Для тех, кому лень читать много английских букв, поясню. VMWare уже давно позволяет запускать на хосте, скажем, с 16 ГБ RAM несколько виртуалок с общей памятью, скажем, 32 ГБ. Как это возможно? Самый старый и избитый способ — подкачка на диск, но он медленный и накладный. Самый «крутой» способ — однократное хранение идентичных областей памяти. Чисто теоретически, в виртуальной памяти двух (и более машин) могут найтись страницы с абсолютно идентичным содержимым, наиболее очевидные кандидаты на идентичность — страницы, занятые ядром и системными файлами ОС. В этом случае можно в физической памяти хранить такую страницу всего один раз. Это сложно, но круто. Самый же «дешевый» способ — загнать виртуальную машину в стрессовые условия, заставив ее уменьшить свои аппетиты к RAM. Эта технология называется memory ballooning и заключается в том, что вышеозначенный драйвер «надувает» в памяти виртуальной машины некий воздушный шарик, запрашивая у ОС блоки неподкачиваемой памяти. Это приводит к тому, что ОС, лишенная избытка свободной памяти уменьшает все системные кэши, зачищает неиспользуемые страницы в пулах памяти приложений и т.п., т.е. подчищает все хвосты, оставляя в памяти только самое нужное. В результате освобождается сколько-то памяти, но драйвер раздувает шарик еще больше, чтобы свободных ресурсов осталось процентов 5-10. В результате хосту нужно отдавать виртуалке не всю заказанную память, а только часть, что для хостеров, конечно, очень выгодно. Если вдруг ОС начинает требовать больше памяти, VMWare это видит и дает Memory Controller команду потихоньку сдувать шарик.
Стоит ли бороться с этим механизмом и отключать его? Если инфраструктура VMWare вам подконтрольна, то и решать вам. Лично я всегда старался размещать виртуалки по хостам так, чтобы они не только полностью туда влезали, но еще оставался небольшой запас RAM на всякий случай. Если вы хостите виртуалку у какого-то провайдера, то ему, конечно, интереснее, чтобы ballooning работал, ведь так он может продать больше виртуалок.
Естественный вопрос: как отключить? Есть два способа: прямой и кривой. Прямой — это взять vmx-файл с настройками виртуалки (перед этим ее, конечно, нужно остановить) и прописать там параметр sched.mem.maxmemctl = «0″. Это можно сделать и через настройки виртуалки, в принципе все описано на сайте VMWare. Кривой способ применим в том случае, когда нет у вас возможности поковыряться в настройках виртуалки (на хостинге, например). Для этого достаточно просто отключить злосчастный драйвер. Запускаем редактор реестра и лезем в ветку HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\VMMEMCTL. В ней находим параметр Start и меняем его значение на 4. Перезагружаем виртуалку и радуемся, что никто больше без нашего ведома не жрет память