Всем доброе время суток. Недавно столкнулся с windows system resource manager. Не то чтобы я раньше с ним не сталкивался. Просто как-то не задумывался над этим. Это средство позволяет, кроме всего прочего, задать некий набор ограничений процессам в операционной системе. В частности, возможно ограничение рабочего набора (working set), определенного процесса. В рамках этой заметки я хотел бы разобраться с тем, как это происходит. Не скрою, что в самый первый момент, когда я увидел, как срабатывает этот механизм – я удивился. Меня сразу затерзали сомнения.
Но все же, начнем. С небольшого теста. Используем программу testlimit, которую почему-то не распространяют с sysinternals suite. Это, кстати, тоже удивило меня, когда я попытался ее найти. Сначала настроим WSRM для нашего теста. Для этого нужно создать фильтр для приложения, в нашем случае это testlimit. А за тем – resource allocation policy, в которой мы и определим ограничения для процесса. Делаем вот таким образом:
1. Создаем новый фильтр
2. Задаем новую политику выделения ресурсов, в которой задаем размер рабочего набора в 300МБ
3. Активируем новую политику
Теперь запускаем приложение
Прежде всего следующая командная строка: Testlimit.exe -d 10 -c 100, выделяет 1 Гб памяти, и коснется ее, заставив систему предоставить реальную оперативную память приложению. Подробности об этом процессе смотрите вот тут. Как видно из скриншота – это и происходит. Размер рабочего набора – 1Гб. Но это длится всего несколько секунд. Затем происходит “странное”:
Бабах! Размер рабочего набора уменьшился до 300 МБ, заданных в настройках WSRM. Возникает вопрос – куда делать память? А что если в ней были данные? И как приложения отреагируют на такое поведение? Не станут ли они вдруг падать?
Для того, чтобы ответить на эти вопросы я написал вот такой вот код. Не плюйтесь, я не разработчик а админ, посему код может быть и не красивый:
// memtest1.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <Windows.h> int _tmain(int argc, _TCHAR* argv[]) { char *a = (char*) malloc(1024*1024*1024); for (int k = 0; k<=100; ++k) { for (int i = 0; i<=1024*1024*1024-1; ++i){ a[i] = 'a';} std::cout << "allocated" << k << std::endl; Sleep (1000); } int g; std::cin >> g; return 0; }
Данный код просто выделяет память, и активно ее использует – попросту пишет в нее. Теперь создаем новый фильтр,новую политику и запускаем приложение. После урезания рабочего набора приложение продолжает работать, как, собственно и ожидалось. Куда же оно пишет?
Для выяснения этого эпизода воспользуемся приложением RAMMap. Запускаем его и, сразу после запуска приложения testlimit видим следующую картинку:
до урезания
после урезания
Видим список активных страниц, и его размер в 3.5 ГБ. И, собственно Private Bytes - 2.2 ГБ. Через некоторое время, когда сработает WSRM видим совсем другую картину. Размер памяти в списке активных страниц уменьшился на примерно 700МБ, а объем памяти обнуленных страниц вырос на эту цифру. Итого, память не провалилась и никуда не исчезла, система переместила страницы из списка в список, предоставив при этом возможность другим приложениям употребить эту память. Однако есть один интересный момент. Testlimit не использует память а просто выделяет ее. Что будет, если эта память будет активно использоваться? Вернемся к моему тестовому коду для этого, и посмотрим, что покажет RAMMap. А показывает он вот что:
до урезания
после урезания
Картинка примерно та же. Но с некоторыми изменениями. При активном использовании памяти страницы не могут попасть в список обнуленных страниц, поскольку они используются. Таким образом система перемещает часть страниц рабочего набора в список измененных страниц. При этом при дальнейшей работе с памятью размер рабочего набора не изменяется. Тут есть один важный нюанс. Сам факт перемещения данных процесса в список модифицированных страниц говорит о том, что будет подкачка, поскольку вернуть страницы в рабочие наборы можно только освободив их и переместив в список свободных. Таким образом это урезание должно сопровождаться ростом дисковых операций, а так же увеличением счетчиков промахов памяти и подкачки, что и наблюдается:
Сразу после урезания начинается подкачка. Таким образом, использование этого функционала, это не только возможность ограничить различные приложения размером рабочего набора, что может быть полезно, к примеру на терминальных серверах. Это еще и своего рода размен памяти на дисковые операции. Посему – есть смысл тщательно подумать над применением этого инструмента.
Комментариев нет:
Отправить комментарий