Периодически мои подписчики задают мне вопросы о том, как проводить микроархитектурный анализ в 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 нет (и это не реклама).

Какие инструменты вам понадобятся?

  1. xperf. Вам необходимо установить Windows Performance Toolkit, который является частью Windows Assessment and Deployment Kit (Windows ADK). У меня xperf был автоматически добавлен в PATH.

  2. 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, внутри мы увидим все трейсы в текстовом формате. Из них можно извлечь много интересного, но давайте сосредоточимся на двух вещах:

  1. Событии Pmc (счетчик мониторинга производительности):

Pmc,  TimeStamp,   ThreadID, BranchMispredictions, BranchInstructions
  1. Событии 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».

Читать ещё: