воскресенье, 9 октября 2011 г.

WSRM и память с точки зрения админа

Всем доброе время суток. Недавно столкнулся с windows system resource manager. Не то чтобы я раньше с ним не сталкивался. Просто как-то не задумывался над этим. Это средство позволяет, кроме всего прочего, задать некий набор ограничений процессам в операционной системе. В частности, возможно ограничение рабочего набора (working set), определенного процесса. В рамках этой заметки я хотел бы разобраться с тем, как это происходит. Не скрою, что в самый первый момент, когда я увидел, как срабатывает этот механизм – я удивился. Меня сразу затерзали сомнения.
Но все же, начнем. С небольшого теста. Используем программу testlimit, которую почему-то не распространяют с sysinternals suite. Это, кстати, тоже удивило меня, когда я попытался ее найти. Сначала настроим WSRM для нашего теста. Для этого нужно создать фильтр для приложения, в нашем случае это testlimit. А за тем – resource allocation policy, в которой мы и определим ограничения для процесса. Делаем вот таким образом:
1. Создаем новый фильтр
mem1mem2
2. Задаем новую политику выделения ресурсов, в которой задаем размер рабочего набора в 300МБ
mem3mem4
3. Активируем новую политику
mem5

Теперь запускаем приложение
mem6

Прежде всего следующая командная строка: Testlimit.exe -d 10 -c 100, выделяет 1 Гб памяти, и коснется ее, заставив систему предоставить реальную оперативную память приложению. Подробности об этом процессе смотрите вот тут. Как видно из скриншота – это и происходит. Размер рабочего набора – 1Гб. Но это длится всего несколько секунд. Затем происходит “странное”:
mem7

Бабах! Размер рабочего набора уменьшился до 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 видим следующую картинку:

до урезания
mem8

после урезания
mem9

Видим список активных страниц, и его размер в 3.5 ГБ. И, собственно Private Bytes  - 2.2 ГБ. Через некоторое время, когда сработает WSRM видим совсем другую картину. Размер памяти в списке активных страниц уменьшился на примерно 700МБ, а объем памяти обнуленных страниц вырос на эту цифру.  Итого, память не провалилась и никуда не исчезла, система переместила страницы из списка в список, предоставив при этом возможность другим приложениям употребить эту память. Однако есть один интересный момент. Testlimit не использует память а просто выделяет ее. Что будет, если эта память будет активно использоваться? Вернемся к моему тестовому коду для этого, и посмотрим, что покажет RAMMap. А показывает он вот что:

до урезания
mem10

после урезания
mem11

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

mem13mem14

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

Комментариев нет: