Как работает профилировщик С#?
Мне любопытно, как работает обычный профайлер С#?
Существуют ли специальные виджеты на виртуальной машине?
Легко ли сканировать байтовый код для вызовов функций и вводить вызовы для запуска/остановки таймера?
Или это действительно сложно и почему люди платят за инструменты для этого?
(в качестве побочной заметки я нахожу немного интересным, потому что это так редко - google пропустил лодку полностью в поиске " как работает профилятор AС#?" не работает вообще - результаты касаются кондиционеров...)
Ответы
Ответ 1
Существует бесплатный профайлер CLR от Microsoft, версия 4.0.
https://www.microsoft.com/downloads/en/details.aspx?FamilyID=be2d842b-fdce-4600-8d32-a3cf74fda5e1
Кстати, там есть хороший раздел в документе CLR Profiler, в котором описывается, как это работает, подробно, стр. 103. Там источник как часть дистрибутива.
Ответ 2
Легко ли сканировать байтовый код для вызовы функций и ввод вызовов таймер запуска/остановки?
Или это действительно сложно и почему люди платят за инструменты для этого?
Инъекционные вызовы достаточно трудны, чтобы для этого нужны инструменты.
Не только это сложно, это очень косвенный способ найти узкие места.
Причина в том, что узким местом является одно или небольшое количество утверждений в вашем коде, которые отвечают за хороший процент времени, затрачиваемого, время, которое может быть значительно сокращено, то есть оно не является действительно необходимым, то есть расточительным.
ЕСЛИ вы можете указать среднее время включения одной из ваших подпрограмм (включая время ввода-вывода), и ЕСЛИ вы можете умножить ее на сколько раз она была вызвана и делить на общее время, вы можете указать, какой процент времени подпрограмма принимает.
Если процент небольшой (например, 10%), у вас, вероятно, больше проблем в другом месте.
Если процент больше (например, от 20% до 99%), у вас может быть узкое место внутри процедуры.
Итак, теперь вам нужно охотиться за рутиной для нее, глядя на то, что она называет, и сколько времени они берут. Также вы хотите избежать путаницы с рекурсией (bugaboo графов вызовов).
Существуют профилировщики (такие как Zoom для Linux, Shark и другие), которые работают по другому принципу.
Принцип заключается в том, что существует стек вызовов функций, и в течение всего времени, за которое отвечает подпрограмма (либо выполняющая работу, либо ожидая, что другие подпрограммы выполняют работу, которую она запросила), она находится в стеке.
Так что если он отвечает за 50% времени (скажем), то количество времени, которое оно находится в стеке,
независимо от того, сколько раз он был вызван, или сколько времени потребовалось за звонок.
Это не только процедура в стеке, но и конкретные строки кода, которые стоят времени, также находятся в стеке.
Вам не нужно охотиться за ними.
Другое дело, что вам не нужна точность измерения.
Если вы взяли 10 000 образцов стека, то виновные линии будут измеряться на уровне 50 +/- 0,5 процента.
Если вы возьмете 100 образцов, их будет измерять как 50 +/- 5 процентов.
Если вы возьмете 10 образцов, они будут измеряться как 50 +/- 16 процентов.
В каждом случае вы их найдете, и это ваша цель.
(И рекурсия не имеет значения. Все это означает, что данная строка может появляться более одного раза в заданном образце стека.)
По этому вопросу есть много путаницы. Во всяком случае, профилировщики, которые наиболее эффективны для поиска узких мест, это те, которые пробуют стек, на настенные часы и сообщают процент за строкой. (Это легко увидеть, если некоторые гипотезы о профилировании).
Ответ 3
1) Нет такой вещи, как "типичный". Люди собирают информацию о профиле различными способами: время отбирает ПК, проверяет трассировку стека, захватывает количество операций методов/операторов/скомпилированных инструкций, вставляет в код код для сбора счетчиков и, необязательно, вызывает контексты для получения данных профиля в контексте вызова основа. Каждый из этих методов может быть реализован по-разному.
2) Профилирование "С#" и профилирование "CLR". В мире MS вы можете профилировать CLR и back-translate места команд CLR на код С#. Я не знаю, использует ли Mono один и тот же набор команд CLR; если они этого не сделали, тогда вы не могли использовать профилировщик MS CLR; вам придется использовать профилировщик Mono IL. Или вы можете использовать исходный код С# для сбора профилирующих данных, а затем компилировать/запускать/собирать эти данные на совместимом компиляторе MS, Mono или на ком-то, совместимом с С#, или на С#, работающем во встроенных системах, таких как WinCE, где пространство ценно и функции, подобные встроенным CLR, как правило, не учитываются.
Один из способов исходного кода инструмента - использовать преобразования источника-источника, отображать код из его исходного состояния в код, содержащий код сбора данных, а также исходную программу. В этом документе на инструменте кода для сбора данных тестового покрытия показано, как можно использовать систему преобразования программ для вставки зондов тестового покрытия путем вставки операторов, определенных булевых флагов при выполнении блока кода. Счетчик-профилировщик заменяет инструкции для инкремента для этих зондов. Профилировщик времени вставляет вычисления моментальных снимков/дельта для этих зондов. Наш С# Profiler реализует как счетное, так и временное профилирование для исходного кода С# в обоих направлениях; он также собирает данные графа вызовов с использованием более сложных зондов, которые собирают путь выполнения. Таким образом, он может генерировать временные данные на диаграммах вызовов таким образом. Эта схема работает везде, где вы можете получить свои руки на половину приемлемого значения времени разрешения.
Ответ 4
Это ссылка на длинную статью, в которой обсуждаются методы инструментализации и выборки:
http://smartbear.com/support/articles/aqtime/profiling/