Плавающие тормоза это самая неприятная категория инцидентов производительности. Пользователь звонит и говорит, что вчера в районе трёх часов дня программа "всё подвисала", а инженер смотрит на сервер сейчас и видит идеально здоровую систему. Перезагрузка, проверка антивирусом и перезапуск служб ничего не меняют, потому что к моменту диагностики проблемы уже нет. Единственный надёжный способ поймать такой сбой это непрерывный сбор метрик в фоне, и встроенный монитор производительности Windows решает эту задачу без единой сторонней программы. Ниже разобраны устройство счётчиков, настройка пользовательских наборов данных через Data Collector Sets, разумный базовый набор метрик, типовые диагнозы по их комбинациям, управление сбором через logman и методика чтения графиков против базовой линии.

Объекты, счётчики и экземпляры как система координат

PerfMon устроен трёхслойно, и путаница в этих уровнях приводит к бессмысленным сборам. Верхний уровень это объект производительности, логическая категория подсистемы: Processor, Memory, PhysicalDisk, Process, Network Interface. Внутри объекта живут счётчики, конкретные измерения: % Processor Time, Available MBytes, Avg. Disk sec/Read. Третий уровень это экземпляры, потому что один объект может описывать несколько физических или логических сущностей: у процессора это ядра 0, 1, 2 и суммарный экземпляр _Total, у физических дисков это 0 C:, 1 D:, у объекта Process это каждый работающий процесс по имени.

Практический вывод простой. Прежде чем добавлять счётчик, инженер обязан решить, какие экземпляры ему нужны. Снимать Process\Private Bytes по экземпляру _Total не имеет смысла для поиска утечки в конкретной службе, потому что итоговая сумма размоет рост одного процесса. Снимать PhysicalDisk\Avg. Disk sec/Write только по экземпляру C: бессмысленно, если база данных лежит на E:. Хорошая привычка это включать либо конкретный нужный экземпляр, либо звёздочку по всем экземплярам с умеренным их числом, и всегда отдельно _Total там, где он существует. Ещё одна тонкость: некоторые счётчики мгновенные (Available MBytes), некоторые усреднённые за интервал (% Processor Time), а некоторые накопительные скорости (Pages/sec показывает операции в секунду, усреднённые за интервал опроса). От интервала зависит, насколько острые пики видны: при опросе раз в секунду краткая вспышка видна, при опросе раз в минуту она растворяется в среднем.

Пользовательский Data Collector Set с интервалом 15 секунд и кольцевым журналом

Для охоты на редкие тормоза нужен сбор, который работает сутками и не съедает диск. Это достигается связкой пользовательского набора сборщиков данных, бинарного формата и кольцевой записи.

В консоли perfmon.msc путь такой: Data Collector Sets, далее User Defined, создать новый набор вручную, выбрать Create data logs и Performance Counter, добавить нужные счётчики и задать Sample interval 15 секунд. Пятнадцать секунд это рабочий компромисс: загрузка процессора самим сбором ничтожна, файл растёт умеренно, а любая просадка, которая длится дольше полуминуты, гарантированно попадёт в лог хотя бы двумя точками. Для проблем, которые разворачиваются секундами, интервал опускают до одной-двух секунд, но такой сбор уже не оставляют на неделю.

Формат файла выбирается бинарный .blg, он компактнее и быстрее пишется, чем CSV, а открывается тем же PerfMon двойным щелчком или кнопкой с пиктограммой папки. Ключевой шаг это вкладка File в свойствах набора: там задаётся имя с подстановкой даты и там же, в свойствах набора на вкладке Stop Condition и через параметры logman, включается режим circular. Кольцевой журнал с лимитом, скажем, 500 мегабайт означает, что старые данные затираются новыми, и на сервере всегда лежит история глубиной в несколько дней без риска переполнить системный раздел. Именно circular-режим превращает PerfMon из инструмента разовой диагностики в постоянный сторож. Когда пользователь звонит и говорит "тормозило вчера", история уже записана, осталось её открыть.

Базовый набор счётчиков при жалобе на тормоза

Соблазн собрать "все счётчики на всякий случай" вреден: размер файла раздувается, графики превращаются в кашу, и анализ откладывается. Практика показывает, что небольшой, но правильно подобранный набор закрывает подавляющее большинство причин плавающих тормозов на Windows-сервере.

  1. Processor\% Processor Time по экземпляру _Total как общий индикатор загрузки вычислений.
  2. System\Processor Queue Length как счётчик потоков, ожидающих процессор; устойчивые значения выше двух на ядро означают очередь.
  3. Memory\Available MBytes как запас свободной памяти.
  4. Memory\Pages/sec как интенсивность жёстких страничных ошибок, то есть реальной работы со свопом.
  5. PhysicalDisk\Avg. Disk sec/Read и Avg. Disk sec/Write по всем экземплярам как главный индикатор здоровья дисковой подсистемы.
  6. PhysicalDisk\% Disk Time как вспомогательная оценка занятости диска.
  7. Process\Private Bytes по ключевым приложениям для отлова утечек памяти.
  8. Network Interface\Output Queue Length и Bytes Total/sec, если есть подозрение на сеть.

Из этого списка особого внимания заслуживает Avg. Disk sec/Read и Avg. Disk sec/Write, потому что это задержка в секундах на одну операцию. Порог, которым оперируют практики, прост: значения до 0,010 секунды это хорошо, до 0,020 терпимо, устойчиво выше 0,020 секунды, то есть двадцати миллисекунд, дисковая подсистема уже тормозит, а выше пятидесяти миллисекунд пользователи это чувствуют явно. Этот счётчик ценен тем, что не зависит от того, перегружен ли диск собственной очередью или само устройство медленное: он измеряет итоговую задержку, которую и переживает приложение. Processor Queue Length при этом помогает отличить недостаток процессора от его простой занятости: сто процентов утилизации при пустой очереди это плотная, но здоровая работа, а та же загрузка при очереди из десяти потоков это уже дефицит.

Типовые диагнозы по комбинациям счётчиков

Сила PerfMon не в отдельных числах, а в комбинациях. Одни и те же внешние жалобы "всё медленно" дают совершенно разные картины на графиках, и читать их нужно как срез нескольких метрик одновременно.

Свопинг это классика: Available MBytes проседает до считанных сотен или десятков, Pages/sec взлетает в сотни и тысячи, а заодно растёт Avg. Disk sec/Read на системном диске, где лежит файл подкачки. Диагноз: нехватка оперативной памяти, система листает страницы, и тормозит не диск сам по себе, а память заодно с диском. Лечится добавлением памяти или сокращением потребителей, и здесь же помогает Process\Private Bytes: если чей-то график растёт ступенями день за днём и не отдаёт память назад, это утечка в конкретном процессе, а не общий дефицит ресурса.

Чистая дисковая проблема выглядит иначе: память в порядке, Pages/sec низкий, процессор недогружен, но Avg. Disk sec/Write уходит за двадцать-пятьдесят миллисекунд ровно в моменты жалоб. Частый виновник это фоновые задачи: антивирусное сканирование, дефрагментация, резервное копирование, перестроение индексов базы. Отметка времени вспышки почти мгновенно сводится с расписанием таких задач в Планировщике.

Процессорная нехватка: % Processor Time упёрся в потолок, Processor Queue Length стабильно выше двух на ядро, память и диск спокойны. Если при этом один процесс по счётчику Process\% Processor Time занимает массивную долю, вопрос переходит уже к приложению, а не к железу.

Сетевые паузы хитрее: на сервере всё ровно, а тормозят операции, уходящие наружу, например к файловой шаре или базе. Здесь помогают Output Queue Length интерфейса и корреляция с всплесками Bytes Total/sec. Наконец, бывает, что все локальные счётчики безупречны, а тормоза есть: тогда PerfMon ставят уже на удалённой стороне обмена, потому что беда живёт не на этом сервере.

logman как консольное управление сбором в том числе на удалённом сервере

Графическая консоль удобна один раз, а разворачивать типовой сбор на парке серверов удобнее командой. Утилита logman входит в состав Windows и делает всё то же самое без мыши.

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

logman create counter BaseWatch -si 15 -f bin -max 500 --v -o "C:\PerfLogs\base.blg" -c "\Processor(_Total)\% Processor Time" "\Memory\Available MBytes" "\Memory\Pages/sec" "\PhysicalDisk(*)\Avg. Disk sec/Read" "\PhysicalDisk(*)\Avg. Disk sec/Write" "\System\Processor Queue Length"

Запуск и остановка:

logman start BaseWatch
logman stop BaseWatch

Кольцевой режим задаётся ключом -max совместно с форматом bin, а при необходимости расписания добавляются параметры начала и конца по времени. Удалённое управление выполняется через ключ -s с именем сервера:

logman create counter BaseWatch -s SRV-APP-07 ...
logman start BaseWatch -s SRV-APP-07
logman query -s SRV-APP-07

Это позволяет инженеру с рабочей станции поднять идентичный сбор на десятке серверов одной строкой в цикле, проверить статус через logman query и забрать готовые .blg-файлы по административным шарам. Скрипт с тем же набором счётчиков становится частью стандартного плейбука реагирования на жалобы, и его повторный запуск занимает секунды вместо десятиминутного кликанья по мастеру.

Чтение графиков через базовую линию и момент жалобы

Открытый .blg сам по себе ничего не доказывает, пока не сравнен с нормой. Понятие базовой линии простое: это поведение тех же счётчиков в те же часы тех же дней в недели, когда жалоб нет. Сервер, у которого Pages/sec всегда держится около нуля, и сервер, который живёт на трёхстах страницах в секунду и не жалуется, требуют разной реакции на одинаковое число. Поэтому полезно иметь эталонный сбор за тихую неделю и сверяться с ним, а не с абстрактными порогами из книг.

Методика разбора конкретного инцидента выглядит как воронка. Сначала в PerfMon открывается журнал и временная шкала подгоняется к окну жалобы с запасом по часу в обе стороны. Дальше выделяется момент жалобы: пользователь сказал "где-то без двадцати три", значит анализируется участок 14:30-15:00. На этом отрезке инженер ищет выбросы против базовой линии: не абсолютные значения, а отклонения от привычного рисунка. Подсветка выбранного счётчика клавишей Ctrl+H в PerfMon выкрашивает его линию, что спасает, когда графиков двадцать. Найденный выброс проверяется спутниками: выросла ли одновременно очередь процессора, просела ли память, подскочила ли дисковая задержка. Совпадение нескольких счётчиков во времени и есть корреляция, которая превращает догадку в диагноз. Если всплеск Pages/sec, падение Available MBytes и рост дисковой задержки совпали с минутой жалобы, история "мне показалось" закрывается цифрами.

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

Почему встроенный сбор ценен именно на проде

Отдельного абзаца заслуживает вопрос, зачем всё это, если существуют полноценные мониторинги. Ответ практический: на многих продуктивных серверах установка стороннего агента требует согласований, смены управления изменениями, проверок безопасности, и пока всё это согласуется, плавающий инцидент повторяется ещё трижды. PerfMon и logman уже есть в системе, их не нужно ставить, они работают под обычной учётной записью с правами Performance Log Users, пишут локально и не открывают лишних портов. Нагрузка самого сбора при интервале пятнадцать секунд и десятке счётчиков незаметна даже на устаревшем железе.

Второе преимущество это доверие и воспроизводимость. Бинарный журнал можно отдать коллеге, вендору или службе поддержки приложения, и он откроется на любой машине с Windows без установки чего-либо. Третье это глубина истории: кольцевой журнал на выделенном разделе копит недели поведения, и когда инцидент наконец повторяется, никто не ждёт его снова, запись уже существует. Именно сочетание нулевой стоимости развёртывания, постоянства наблюдения и легко передаваемого формата делает встроенный сбор первым шагом любой охоты на плавающие тормоза, ещё до разговоров о специализированных платформах мониторинга. Дисциплина простая: типовой BaseWatch развёрнут на каждом сервере заранее, через logman, с кольцевым лимитом, и инцидент перестаёт быть лотереей.