Быстрый ответ: дайте этой рутине меньше работы. Что я думаю, означает либо использовать меньше виртуального адресного пространства за один раз, либо добавить больше оперативной памяти.
Детали: во-первых, процедура, которую вы видите, MiWalkPageTablesRecursively
, имеет мало общего с файлом страницы напрямую, а скорее с таблицами страницы. Таблицы страниц являются структурами в памяти (и присутствуют во всех системах Windows независимо от конфигурации файла подкачки). Каждый процесс имеет набор таблиц страниц, а также набор адресного пространства ОС ("пространство ядра").
Таблицы страниц состоят из записей таблицы страниц; есть один PTE для каждой страницы - 4K - определенного виртуального адресного пространства процесса. Под "определенным" я подразумеваю, что оно включает отображенное и частное зафиксированное адресное пространство процесса и регионы AWE, если таковые имеются; оно не включает зарезервированное или свободное адресное пространство - регионы, которые могут вызвать нарушение прав доступа, если вы попытаетесь их прочитать или записать.
(Кстати: у вас не только будут таблицы страниц, даже если у вас нет файла подкачки. Вы также по-прежнему будете иметь страницы и сбои страниц на диске и с диска, даже если у вас нет файла подкачки.)
Проблема здесь, вероятно, не присуща MiWalkPageTablesRecursively
. Ведь эта функция (или эквивалент под другим именем) была частью Windows начиная с NT 3.1. Дело в том, что приходится много работать. Это, вероятно, означает, что его часто вызывают.
Подсказка, почему это так, видна в подпрограммах, ранее находящихся в стеке. (То есть ближе к верхней части дисплея WPA.) Похоже, что вызывающим MiWalkPageTablesRecursively
в этом сценарии является MiWalkPageTables
, который в свою очередь вызывается MiAgeWorkingSet
, который, в свою очередь, вызывается MiTrimOrAgeWorkingSet
, который, в свою очередь, вызывается MiProcessWorkingSets
, который, в свою очередь, вызывается ... это так далеко, как нам нужно идти.
Каждый процесс в системе Windows имеет структуру, называемую "список рабочих наборов". Это список всех номеров физических страниц, которые были сбиты в ОЗУ в результате сбоев страниц процесса. Поток (поток "Balance Set Manager") пробуждается раз в секунду для очистки и обслуживания каждого рабочего набора процесса. Таким образом, MiProcessWorkingSets
выполняет итерации по процессам, по очереди работая с рабочим набором каждого процесса.
Для каждого процесса в системе MiProcessWorkingSets
вызывает MiTrimOrAgeWorkingSet
. Это имя подпрограммы относится к "обрезке" рабочего набора (что означает идентификацию давно неиспользуемых страниц и удаление их из процесса, чтобы освободить место в ОЗУ для других вещей), или "старению" рабочего набора, что означает увеличение "возраста" счетчик для каждой записи списка рабочих наборов, к которой не обращались с момента последнего сканирования, или обнуление счетчика, если оно было. (Название относится к задаче "старения", которая выполняется в бухгалтерском учете, обычно каждый месяц или каждый день.) Счетчик "age" затем используется функцией "trim" для идентификации наиболее неиспользуемых страниц.
Из факта, что MiTrimOrAgeWorkingSet
заканчивается в MiWalkPageTablesRecursively
, мы можем сделать вывод, что они сканируют виртуальное адресное пространство, как определено таблицами страниц, чтобы найти страницы, которые находятся в рабочем наборе. Теперь рассмотрим: время, необходимое MiTrimOrAgeWorkingSet
для обработки каждого процесса, будет примерно пропорционально размеру виртуального адресного пространства процесса. И общее время, необходимое для каждого прохождения через MiProcessWorkingSets
будет примерно пропорционально количеству процессов.
Либо эта вещь имеет дело с очень большим количеством страниц в рабочем наборе одного процесса, либо она имеет дело с большим количеством процессов.
И ... с чего бы это быть таким занятым? Он не "обрезает" рабочие наборы до тех пор, пока они не состарятся, и количество, на которое "обрезает" рабочие наборы, зависит от нагрузки на ОЗУ, то есть от того, насколько мало у вас ОЗУ.
Ваша система не хватает оперативной памяти? Пожалуйста, опубликуйте снимки вкладки «Диспетчер задач» | Страница памяти плюс страница «Подробности», отсортированная по столбцу «Рабочий набор»; плюс вкладка Память монитора ресурсов, отсортированная по столбцу Hard Faults; и страницу использования счетчиков RAMmap.
Кроме того, пожалуйста, опубликуйте больше ваших трассировок WPA, показывая больше "глубины" вызовов. Или разместите файл .etl где-нибудь на сервисе обмена ссылками и дайте ссылку на него здесь. (Сначала застегните молнию - они сжимаются очень хорошо.)
В сторону: почему имена подпрограмм не совпадают между WPA и Process Explorer
Что касается имен подпрограмм, то реальным вопросом будет «почему имена подпрограмм, отображаемые в Process Explorer, просто неверны». Есть две причины для этого в вашем случае, и вы должны исправить обе из них.
Первая проблема заключается в том, что, похоже, у вас неправильно настроены символы для Process Explorer. Конфигурирование их для Windows Performance Analyzer недостаточно.
Верным признаком того, что у вас нет этого права, является то, что все или почти все потоки в процессе "Система" отображаются с именем модуля (нечто.sys или что-то.exe, обычно ntoskrnl.exe), за которым следует смещение , например, +0x245
- как в шапке экрана. Можно видеть несколько таких, но вы должны увидеть целую кучу ntoskrnl!рутинное имя с последующим без смещения.
Чтобы это исправить, см. Эту страницу в Руководстве по анализу производительности Windows. Вам нужно установить путь поиска символов в Process Explorer - вы можете использовать тот же путь к файлу символов, который вы установили для WPA, - и вам нужно указать ProcExp на DLL, которая поставляется с Windows Debugging Tools. Поэтому вам нужно будет установить средства отладки - не то, что вы используете отладчик напрямую, а Process Explorer нужна эта DLL.
Вторая причина расхождения заключается в том, что даже после правильной настройки файлов символов для Process Explorer отображаемые имена подпрограмм не всегда совпадают с именами подпрограмм внутреннего уровня, определенных Performance Analyzer. Тем не менее, вы должны найти совпадение в имени процедуры в начале стека (отображается в верхней части дерева вызовов процедуры, как показано в WPA).
Например, в вашем случае первая интересная процедура - KeBalanceSetManager
. (Два предыдущих варианта одинаковы для каждого потока в системном процессе, но KeBalanceSetManager
- это процедура "верхнего уровня" для этого потока.) После того, как вы правильно настроили символы, Process Explorer должен показать вам поток с "Начальным адресом", как показано здесь:
Process Explorer не может показать вам MiWalkPageTablesRecursively
потому что это около шести вызовов в стек из того, что записано как начальный адрес потока, и это даже не текущая внутренняя подпрограмма (т.е. она не находится на вершине стека). Такая информация (даже если она легко доступна, а это не так) будет меняться слишком быстро, чтобы быть полезной на дисплее Process Explorer, поэтому она не пытается.
Примечание. Даже с правильными символами нередко можно найти несколько потоков в системном процессе, показывающих "Начальный адрес", например, GemCCID.sys+0xd138
, как вы увидите в моем примере. Рассматриваемый модуль (GemCCID.sys), очевидно, не является тем, для которого Microsoft предоставляет файлы символов, поэтому Process Explorer просто должен сказать, что «начальный адрес потока находится в 0xd138 байтах от начала кода в этом файле, и это все, что я знать об этом. "
Надеюсь это поможет! Пожалуйста, дайте мне знать, если у вас есть дополнительные вопросы.