Быстрый ответ: дайте этой рутине меньше работы. Что я думаю, означает либо использовать меньше виртуального адресного пространства за один раз, либо добавить больше оперативной памяти.
Детали: во-первых, процедура, которую вы видите, MiWalkPageTablesRecursively
имеет непосредственное отношение не к файлу страницы, а к таблицам страниц . Таблицы страниц являются структурами в памяти (и присутствуют во всех системах Windows независимо от конфигурации файла подкачки). Каждый процесс имеет набор таблиц страниц, а также набор адресного пространства ОС («пространство ядра»).
Таблицы страниц состоят из записей таблицы страниц; есть один PTE для каждой страницы - 4K - определенного виртуального адресного пространства процесса. Под «определенным» я подразумеваю, что оно включает отображенное и частное зафиксированное адресное пространство процесса и регионы AWE, если таковые имеются; оно не включает зарезервированное или свободное адресное пространство - регионы, которые могут вызвать нарушение прав доступа, если вы попытаетесь их прочитать или записать.
(Между прочим: у вас не только будут таблицы страниц, даже если у вас нет файла подкачки. У вас также останутся страницы и ошибки страниц на диске и с диска, даже если у вас нет файла подкачки.)
Проблема здесь, вероятно, не присуща MiWalkPageTablesRecursively
. Ведь эта функция (или эквивалент под другим именем) была частью Windows начиная с NT 3.1. Дело в том, что приходится много работать. Это, вероятно, означает, что его часто вызывают.
Подсказка, почему это так, видна в подпрограммах, ранее находящихся в стеке. (То есть ближе к верхней части экрана WPA.) Похоже, что вызывающий объект MiWalkPageTablesRecursively
в этом сценарии MiWalkPageTables
, который, в свою очередь, вызывается MiAgeWorkingSet
, который, в свою очередь, вызывается MiTrimOrAgeWorkingSet
, который, в свою очередь, вызывается MiProcessWorkingSets
, который в свою очередь вызывается ... это так далеко, как нам нужно идти.
Каждый процесс в системе Windows имеет структуру, называемую «список рабочих наборов». Это список всех номеров физических страниц, которые были сбиты в ОЗУ в результате сбоев страниц процесса. Поток (поток «Balance Set Manager») пробуждается раз в секунду для очистки и обслуживания каждого рабочего набора процесса. Так MiProcessWorkingSets
итерирует по процессам, работая с рабочим набором каждого процесса по очереди.
Для каждого процесса в системе MiProcessWorkingSets
звонки MiTrimOrAgeWorkingSet
. Это имя подпрограммы относится к «обрезке» рабочего набора (что означает идентификацию давно неиспользуемых страниц и удаление их из процесса, чтобы освободить место в ОЗУ для других вещей), или «старению» рабочего набора, что означает увеличение «возраста» счетчик для каждой записи списка рабочих наборов, к которой не обращались с момента последнего сканирования, или обнуление счетчика, если оно было. (Название относится к задаче «старения», которая выполняется в бухгалтерском учете, обычно каждый месяц или каждый день.) Затем счетчик «возраста» используется функцией «обрезки» для идентификации наиболее неиспользуемых страниц.
Из того, что 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 байтах от начала кода в этом файле, и это все, что я знать об этом. "
Надеюсь это поможет! Пожалуйста, дайте мне знать, если у вас есть дополнительные вопросы.