Периодически мои подписчики задают мне вопросы о том, как проводить микроархитектурный анализ в Windows? Если честно, это никогда не представляло для меня какой-то особой проблемы. Угадайте почему? Потому что я работаю в Intel и, конечно же, у меня есть лицензия для использования Intel® VTune™ Amplifier. Поэтому я не могу полностью прочувствовать боль людей, которые заняты работой, связанной с производительностью в Windows, и не имеют доступа к Vtune или AMD CodeAnalyst. Поскольку это не было для меня проблемой, я ничего не предпринимал для ее решения. Наконец, недавно я просматривал блог Бартека посвященный кодингу и наткнулся на статью «Любопытный случай с производительностью бранчинга». Мне это показалось случаем, который можно легко проверить, просто запустив perf stat, если бы мы работали в Linux. Но поскольку мы работаем в Windows… все не так просто.
В этой статье я хочу представить один из способов сбора PMU-счетчиков без Intel® VTune™ Amplifier. Почти всю необходимую информацию я взял из блога Брюса Доусона. Он написал статью, которую я хочу расширить и сделать ее более пошаговой. Т.е., все лавры здесь принадлежит Брюсу, потому что не я автор этой работы. Если вы хотите поэкспериментировать сами, я предлагаю вам сначала воспроизвести пример, описанный в статье Брюса (вот ссылка на github с исходниками и скриптами).
Однако не воспринимайте все, что написано в моей статье, за чистую монету. Я не Windows-разработчик и не трачу много времени на анализ производительности в Windows. Это всего лишь один из способов сбора PMU-счетчиков — могут быть и другие, более простые и надежные. В конце концов, вы всегда можете приобрести Intel® VTune™ Amplifier, который, кстати, может быть довольно дорогим. Но сразу хочу сказать, что, если вы собираетесь проводить серьезный анализ производительности и тюнинг в Windows, реальных альтернатив Vtune нет (и это не реклама).
Какие инструменты вам понадобятся?
xperf. Вам необходимо установить Windows Performance Toolkit, который является частью Windows Assessment and Deployment Kit (Windows ADK). У меня xperf был автоматически добавлен в PATH.
tracelog. Следуйте этим инструкциям, чтобы получить этот инструмент. Вам необходимо установить следующие компоненты:
Windows Driver Kit
Visual Studio
Windows SDK
Tracelog не был добавлен в мой PATH, но мне удалось найти его по следующему пути: "C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x64\
". У вас этот путь может отличаться.
Для установки всех этих комплектов потребуется некоторое время, поэтому запаситесь терпением.
Использование tracelog и xperf для сбора трейсов
Я буду использовать пример, приведенный Брюсом, частично повторяя его действия. Вот как вы можете получить трейсы (с информацией о неправильных прогнозах бранчинга) из своего приложения, используя упомянутые выше инструменты (следует запускать от имени администратора):
tracelog.exe -start counters -f counters.etl -eflag CSWITCH+PROC_THREAD+LOADER -PMC BranchMispredictions,BranchInstructions:CSWITCH
<your app>
xperf -stop counters
xperf -merge counters.etl pmc_counters_merged.etl
xperf -i pmc_counters_merged.etl -o pmc_counters.txt
Если мы заглянем в pmccounters.txt, внутри мы увидим все трейсы в текстовом формате. Из них можно извлечь много интересного, но давайте сосредоточимся на двух вещах:
Событии Pmc (счетчик мониторинга производительности):
Pmc, TimeStamp, ThreadID, BranchMispredictions, BranchInstructions
Событии CSwitch (переключение контекста):
CSwitch, TimeStamp, New Process Name ( PID), New TID, NPri, NQnt, TmSinceLast,
WaitTime, Old Process Name ( PID), Old TID, OPri, OQnt, OldState,
Wait Reason, Swapable, InSwitchTime, CPU, IdealProc, OldRemQnt, NewPriDecr,
PrevCState, OldThrdBamQosLevel, NewThrdBamQosLevel
Рассмотрим этот фрагмент трейса:
Pmc, 214810, 5956, 1101534, 44324578
CSwitch, 214810, ConditionalCount.exe (14224), 5956, 9, -1, 6, 0, System ( 4), 560, 12, -1, Waiting, WrQueue, NonSwap, 6, 1, 3, 84017152, 0, 0, Important, Important
Pmc, 214821, 14460, 1101713, 44326484
CSwitch, 214821, csrss.exe ( 888), 14460, 14, -1, 73556, 5, ConditionalCount.exe (14224), 5956, 9, -1, Waiting, WrLpcReply, Swapable, 11, 1, 3, 77701120, 0, 0, Important, Important
Обратите внимание, что для каждого события CSwitch есть соответствующее событие Pmc. Мы видим, что они имеют одинаковые таймстемпы. В этом фрагменте трейса произошло переключение контекста с нашего процесса (ConditionalCount.exe
) на другой процесс (csrss.exe
). Мы можем увидеть это, посмотрев на Old Process Name (PID) события CSwitch с таймстемпом 214821. Т.е. был некоторый период времени, в течение которого ConditionalCount.exe
выполнялся на ЦП (между таймстемпами 214821 и 214810).
Значение счетчика BranchMispredictions постоянно увеличивается. Мы можем подсчитать, сколько было ошибочных прогнозов бранчинга за этот период времени, посчитав разницу этих значений в двух событиях Pmc. Для этого фрагмента было 1101713 - 1101534 = 179 неверных прогнозов бранчинга. Суммируя все дельты, мы можем рассчитать общее количество ошибочных прогнозов бранчинга за все время работы приложения.
Совет от профессионала: если вы наблюдаете показатели, которые отличаются от ожидаемых, я все таки рекомендую вам попробовать запустить тот же бенчмарк в Linux с помощью команды perf stat
. Вы можете найти множество статей о том, как это сделать, в моем блоге. Другой способ - сбросить сборку и проверить наличие ожидаемого кода. Возможно, компилятор сделал что-то умное и удалил код, который вы хотели протестировать.
Анализ трейсов с помощью скрипта Python
Для анализа трейсов и извлечения информации Брюс написал специальный скрипт. Этот скрипт извлекает значения PMC для процессов, которые нас интересуют (2 аргумента):
python.exe etwpmcparser.py pmccounters.txt <your app>
Вот результат, который я получил на своем компьютере (Win 10, Intel (R) Core (TM) i5-7300U).
Process name: branch misp rate, [br_misp, total branc]
ConditionalCount.exe (14224): 21.91%, [109184040, 498250335], 3690 context switches, time: 1093072
ConditionalCount.exe (10964): 0.07%, [369677, 496453009], 761 context switches, time: 257492
Vtune показывает аналогичные результаты.
Какие еще счетчики мы можем собрать?
> tracelog.exe -profilesources Help
Id Name Interval Min Max
--------------------------------------------------------------
0 Timer 10000 1221 1000000
2 TotalIssues 65536 4096 2147483647
6 BranchInstructions 65536 4096 2147483647
10 CacheMisses 65536 4096 2147483647
11 BranchMispredictions 65536 4096 2147483647
19 TotalCycles 65536 4096 2147483647
25 UnhaltedCoreCycles 65536 4096 2147483647
26 InstructionRetired 65536 4096 2147483647
27 UnhaltedReferenceCycles 65536 4096 2147483647
28 LLCReference 65536 4096 2147483647
29 LLCMisses 65536 4096 2147483647
30 BranchInstructionRetired 65536 4096 2147483647
31 BranchMispredictsRetired 65536 4096 2147483647
Заключение
Этот метод еле-еле дотягивает до того, что умеют делать Vtune или perf в Linux. Количество счетчиков ограничено, и это только подсчет без сэмплинга (см. разницу между подсчетом и сэмплингом здесь). Так-то это так, но, по крайней мере, вы можете провести предварительный анализ производительности.
Во-вторых, если вы хотите собрать разные PMC, отличные от неправильного прогнозирования бранчинга, вам необходимо изменить не только команду tracelog
, но и скрипт python, который анализирует трейсы.
Если вы знаете какой-либо другой способ сделать это проще или лучше, дайте мне знать. Я определенно хотел бы узнать его.
Я надеюсь, что это также поможет людям, которые используют Windows и хотят участвовать в моем конкурсе. Если это так, подписывайтесь с помощью формы внизу страницы.
Перевод данной статьи был подготовлен в преддверии старта курса «Нагрузочное тестирование».
Также приглашаем всех желающих зарегистрироваться на демо-урок курса по теме «Проведение нагрузочного тестирования в средстве Performance center».
ol_x
Ох… шлак. В системе хватает всякого API, начиная от реестра до агрегированной обертки PDH, а если этого мало, то ETW в помощь. Все это необходимо сводить к максимальной автоматизации — проще написать под себя, что-то стороннее подходит только для ручного просмотра