Предотвращение погружения тяжелого процесса в файл подкачки - PullRequest
6 голосов
/ 07 мая 2009

Наш сервис, как правило, засыпает по ночам на сервере нашего клиента, а затем с трудом просыпается. Кажется, что происходит, что куча процесса, которая иногда составляет несколько сотен МБ, перемещается в файл подкачки. Это происходит ночью, когда наш сервис не используется, а другие запланированы к запуску (резервное копирование БД, сканирование AV и т. Д.). Когда это происходит, после нескольких часов бездействия первый звонок в службу занимает несколько минут (последующие звонки занимают секунды).

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

Я смутно помню, что есть способ заставить Windows хранить страницы в физической памяти, но я действительно ненавижу эту идею. Я больше склоняюсь к некоторому внутреннему или внешнему сторожевому сигналу, который будет инициировать высокоуровневые функции (уже есть какой-то внутренний планировщик, который делает очень мало и не имеет значения). Если бы существовал сторонний инструмент, обеспечивающий такой вид обслуживания, он был бы таким же хорошим.

Мне бы очень хотелось услышать любые комментарии, рекомендации и общие решения для такого рода проблем. Сервис написан на VC2005 и работает на серверах Windows.

Ответы [ 5 ]

8 голосов
/ 07 мая 2009

Как вы упомянули, принудительное сохранение приложения в памяти - не лучший способ совместного использования ресурсов на компьютере. Быстрое решение, которое вам может пригодиться, - это просто запланировать событие, которое будит ваш сервис в определенное время каждое утро, прежде чем ваши клиенты начнут его использовать. Вы можете просто запланировать это в планировщике задач Windows с помощью простого скрипта или вызова EXE.

2 голосов
/ 16 марта 2010

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

Сводка: регулярно касайтесь каждой страницы в процессе, на странице за раз.

Как насчет потока, который работает в фоновом режиме и просыпается один раз каждые N секунд. Каждый раз, когда страница просыпается, она пытается прочитать с адреса X. Попытка защищена обработчиком исключений на случай, если вы прочитали неверный адрес. Затем увеличьте X на размер страницы.

65536 страниц в 4 ГБ, 49152 страницы в 3 ГБ, 32768 страниц в 2 ГБ. Разделите время простоя (ночное время простоя) на то, как часто вы хотите (пытаетесь) попасть на каждую страницу.

BYTE *ptr;

ptr = NULL;
while(TRUE)
{
    __try
    {
        BYTE b;

        b = *ptr;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        // ignore, some pages won't be accessible
    }

    ptr += sizeofVMPage;

    Sleep(N * 1000);
}

Вы можете получить значение sizeOfVMPage из значения dwPageSize в возвращенном результате из GetSystemInfo ().

Не пытайтесь избежать обработчика исключений, используя if (! IsBadReadPtr (ptr)), потому что другие потоки в приложении могут одновременно изменять защиту памяти. Если вы отстегнетесь из-за этого, почти невозможно определить причину (это, скорее всего, будет не повторяемое состояние гонки), поэтому не тратьте время на это.

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

1 голос
/ 16 марта 2010

Другая вещь, которую нужно гарантировать, это то, что ваши данные локализованы.

Другими словами: вам действительно нужны все 300 МБ памяти, прежде чем вы сможете что-либо сделать? Можно ли перестроить используемые вами структуры данных так, чтобы любой конкретный запрос мог быть удовлетворен всего несколькими мегабайтами?

Например

  • , если ваши 300 МБ памяти кучи содержат данные распознавания лиц. Могут ли данные быть организованы так, чтобы данные мужского и женского лица хранились вместе? Или большие носы отделены от маленьких носов?

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

  • если это движок базы данных, работающий в памяти, может ли данные быть лучше проиндексированы / кластеризованы, чтобы не требовалось так много обращений к страницам памяти?

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

Вам действительно нужно все 300 МБ памяти, прежде чем вы сможете что-либо сделать? Вы не можете обработать запрос без всех этих данных в памяти?


В противном случае: запланированное задание на 6 ᴀᴍ, чтобы разбудить его.

1 голос
/ 07 мая 2009

Третий подход может состоять в том, чтобы ваша служба запускала поток, который выполняет что-то тривиальное, например, увеличивает счетчик, а затем спит в течение довольно длительного периода, скажем, 10 секунд. Thios должен оказывать минимальное влияние на другие приложения, но по крайней мере некоторые из ваших страниц должны быть доступны.

0 голосов
/ 07 мая 2009

С точки зрения стоимости, самое дешевое и простое решение - просто купить больше оперативной памяти для этого сервера, а затем полностью отключить файл подкачки. Если вы используете 32-битную Windows, просто купите 4 ГБ оперативной памяти. Тогда все адресное пространство будет обеспечено физической памятью, и файл подкачки ничего не будет делать.

...