Упражнение 3. Понимание критического пути и анализа ожидания
Сценарии и действия могут быть неожиданно отложены. Например, открытие вкладки в Microsoft Edge иногда может занять больше времени, чем ожидалось.
Действие определяется как ряд операций, некоторые последовательные и параллельные, которые передаются от события запуска к событию end. Любая пара событий начала и окончания в трассировке может рассматриваться как действие. Самый длинный путь в этой серии операций называется критическим путем. Уменьшение длительности любой операции на критическом пути напрямую сокращает длительность общей активности.
Рекомендуется определить процесс и поток, который завершил действие, и работать в обратном направлении с момента завершения действия. Начните с анализа потока, который завершил действие, чтобы определить, как этот поток провел большую часть своего времени и в каком состоянии: выполняется, готов или ожидает.
Значительное время выполнения указывает на то, что прямое использование ЦП может способствовать длительности критического пути. Время, затраченное в состоянии готовности , указывает на то, что другие потоки влияют на длительность критического пути, препятствуя выполнению потока на критическом пути. Время, затраченное на точки ожидания ввода-вывода, таймеры или другие потоки и процессы на критическом пути, для которого ожидал текущий поток.
Каждый поток, который считывает текущий поток, вероятно, является еще одним звеном в критическом пути и также может быть проанализирован до тех пор, пока не будет учитываться длительность критического пути.
Все необходимые сведения записываются в диаграмму и таблицу загрузка ЦП (точная) в WPA. События использования ЦП, которые регистрируются диспетчером, связаны с коммутаторами контекста. В этой таблице основное внимание уделяется NewThread — потоку, который был переключен, и каждая строка представляет переключатель контекста. Данные собираются для следующей последовательности событий:
Функция NewThread отключена из-за вызова функции блокировки.
NewThread готов к запуску потоком подготовки.
NewThread включается, тем самым выключая старый поток.
NewThread снова выключается.
Ниже приведены интересные столбцы в таблице Загрузка ЦП (точная).
Столбец | Сведения |
---|---|
% загрузки ЦП | Загрузка ЦП новым потоком после его переключения. Это значение выражается в процентах от общего времени ЦП за текущий видимый период времени. |
Count | Число переключений контекста, представленных строкой. Это значение всегда равно 1 для отдельных строк. |
Загрузка ЦП (мс) | Загрузка ЦП новым потоком после переключения контекста. |
NewProcess | Процесс нового потока. |
NewThreadId | Идентификатор нового потока. |
NewThreadStack | Стек нового потока при его включении. Обычно указывает, что поток был заблокирован или ожидается. |
Готовые | Время, затраченное потоком в очереди Готово (из-за упреждающего голода или нехватки ЦП). |
ReadyingThreadId | Идентификатор потока подготовки. |
ReadyingProcess | Процесс, которому принадлежит поток подготовки. |
ReadyThreadStack | Стек потока подготовки. |
ReadyTime (s) | Время подготовки нового потока. |
SwitchInTime(s) | Время переключения нового потока. |
Ожидания (с) | Время ожидания потока для логического или физического ресурса. Ожидание заканчивается, когда NewThreadId получает сигнал ReadyingThreadId. |
Шаг 1. Запись и открытие трассировки для проблемы с задержкой пользовательского интерфейса
В этом упражнении основное внимание уделяется фиктивному процессу с пользовательским интерфейсом без ответа. Процесс представляет собой простое приложение Windows Forms с кнопкой и текстовым полем. При нажатии кнопки пользовательский интерфейс перестает отвечать на запросы в течение 20 секунд, пока текстовое поле не будет обновлено. Вы проанализируете критический путь этой операции.
Скачайте UIDelay.exeотсюда.
Запустите UIDelay.exe.
Откройте WPR из меню "Пуск ".
Измените конфигурацию трассировки.
Выберите Первый уровень рассмотрения и загрузка ЦП.
Выберите Общие в качестве сценария производительности.
Выберите Уровень детализации подробно.
Нажмите кнопку Пуск.
В UIDelay.exeнажмите кнопку Щелкните .
- Дождитесь, пока в текстовом поле не появится сообщение "Готово!"
В WPR сохраните трассировку и откройте ее с помощью WPA.
Откройте меню Трассировка и выберите Настроить путь к символам.
- Укажите путь к кэшу символов. Дополнительные сведения о символах см. на странице Поддержка символов на сайте MSDN.
Откройте меню Трассировка и выберите Загрузить символы.
Шаг 2. Определение отложенного потока пользовательского интерфейса
Перед выполнением анализа критического пути необходимо сначала определить события запуска и остановки действия.
Найдите граф Задержки пользовательского интерфейса в узле Системное действиеОбозреватель Graph.
Перетащите диаграмму Задержки пользовательского интерфейса на вкладке анализ.
Найдите UIDelay.exe процесс.
Его продолжительность должна составлять около 20 секунд. Это означает, что в потоке пользовательского интерфейсаUIDelay.exeпроизошла задержка в 20 секунд.
Идентификатор потока пользовательского интерфейса отображается в столбце Thread Id (Идентификатор потока ). В этом примере это 24174. Это значение будет отличаться в трассировке, записанной на компьютере. Обязательно запишите идентификатор потока.
Выберите весь интервал времениUIDelay.exe , щелкните правой кнопкой мыши и увеличьте масштаб.
Всегда следует увеличивать масштаб регионов, которые вы пытаетесь проанализировать. Это уменьшает количество шума, вызванного несвязанными действиями.
Шаг 3. Анализ критического пути задержки пользовательского интерфейса
Теперь, когда у вас есть отправная точка анализа с идентификатором потока и метками времени, можно начать изучение критического пути действия, чтобы понять последовательность событий, которые приводят к 20-секундной задержке в потоке пользовательского интерфейса.
NewThreadId для этого шага — это поток, определенный на шаге 2 (поток 24174 в UIDelay.exe процессе).
Добавьте диаграмму Загрузка ЦП (точная) на вкладку анализа и примените предустановку "Использование по процессам" потока .
Щелкните правой кнопкой мыши заголовки столбцов и сделайте столбцы NewThreadStack, ReadyThreadStack и Cpu Usage (ms) видимыми.
Удалите столбцы Ready (us) [Max] и Waits (us) [Max] . Окно просмотра теперь должно выглядеть следующим образом.
Найдите и разверните процессUIDelay.exe в столбце NewProcess и выполните сортировку по waits (us) [Sum] , щелкнув заголовок столбца.
Найдите NewThreadId в процессе UIDelay.exe и проанализируйте его время, затраченное на состояние Выполняется, Готово или Ожидание.
В следующем примере можно найти следующее:
Поток занимает 10,025 секунды времени ЦП.
Поток ожидает 5,159 секунды.
Поток находится в состоянии готовности в течение незначительного количества времени (10 мс).
Примечание Вы можете проанализировать 10 секунд активности ЦП с помощью той же методологии, описанной в упражнении 2, шаг 4, используя диаграмму Использование ЦП (выборка) и просмотрев процессUIDelay.exe .
Чтобы узнать, чего ожидал NewThreadId , разверните группу NewThreadId , чтобы отобразить NewThreadStack.
Разверните [Корень] и определите вызовы функции, ведущие к ожиданиям.
В этом примере UIDelay.exe поток с идентификатором 24174 ожидает вызовов базовой функции блокировки в течение 5,073 секунды при активации функции нажатия кнопки:
5,021 секунды из-за операций под функцией ExecuteWMICall .
35 мс из-за операций под функцией PingServer .
Шаг 3.1. Просмотр пути кода ExecuteWMICall
Если развернуть стек вызовов далее в разделе ExecuteWMICall, вы обнаружите, что поток пользовательского интерфейса фактически находится в спящем режиме в течение 5 секунд, явно вызвав Thread.Sleep.
Такого поведения следует избегать любой ценой, так как это напрямую влияет на скорость реагирования. Если коду нужно ждать сведений, он должен асинхронно выполнять это в отдельном потоке и использовать метод, управляемый событиями.
Шаг 3.2. Просмотр кода PingServer
Если расширить стек вызовов в разделе PingServer, вы увидите, что поток пользовательского интерфейса имеет зависимости ввода-вывода, так как он отправляет команды Ping по сети.
Хотя задержка очень мала (35 мс), ее следует избегать в потоке пользовательского интерфейса. Имейте в виду, что средний пользователь заметит задержку пользовательского интерфейса больше 100 мс. Эта операция может увеличить общее время активности, затраченное более 100 мс, что приводит к тому, что пользователи плохо воспринимают скорость реагирования.
Эти операции должны выполняться асинхронно в отдельном потоке и не блокировать пользовательский интерфейс.