JetBrains dotTrace 3.0 - профайлер для .Net Автор: Виктор Деревянко Опубликовано: 08.08.2008 Источник: SoftKey.info Опытные разработчики программного обеспечения знают, что
"оптимизация имеет смысл только тогда, когда она имеет смысл". Вы разработали программу и обнаружили, что она работает недостаточно быстро? Вначале тщательно определите участки кода, которые действительно нуждаются в оптимизации, и только затем ее проводите. Любая оптимизация, как правило, ведет к появлению в программе кода, который сложно отлаживать, поддерживать и сопровождать, так что "оптимизировать" все подряд не стоит - реального улучшения производительности вы не добъетесь, а стоимость разработки и сопровождения кода может возрасти многократно. Все-таки не зря говорят, что "преждевременная оптимизация есть корень всех зол".
Так что если вас не устраивает производительность вашего приложения - вам необходимо проанализировать его работу, т. е. выполнить профилирование. Для проведения профилирования применяются специальные программы - профайлеры.
Профайлер – это программа, которая наблюдает за работой вашего приложения и выполняет сбор характеристик его работы. С помощью профайлеров можно определить, какие части кода приложения выполняются дольше всего, как приложение использует память, построить граф вызовов функций в приложении, выявить неиспользуемые участки кода в приложении и т. д. и т. п.
JetBrains dotTrace 3.0 - это профайлер для приложений, разработанных для платформы Microsoft Net. Он позволяет вести профилирование настольных (desktop) приложений, веб-приложений, запущенных под IIS или на ASP.NET Development Server, а также сервисов Windows. Поддерживается два вида анализа работы приложений - по производительности и по использованию памяти.
Средства профилирования производительности позволяют идентифицировать в анализируемом приложении медленные участки кода и проводить сравнительный анализ времени выполнения функций до и после оптимизации. Средства анализа использования памяти дают возможность получить детальную структуру размещения объектов в памяти, определить, какие классы и пространства имен расходуют памяти больше всего, посмотреть список достижимых и удерживаемых объектов для любого выбранного объекта, а также список объектов, подлежащих удалению "сборщиком мусора".
 | | Окно запуска процесса профилирования |
Принцип использования программы dotTrace следующий. Вы запускаете dotTrace, выбираете приложение, которое будете анализировать, указываете требуемый тип анализа и его параметры. По вашей команде dotTrace запускает приложение и открывает окно управления, позволяющее контролировать процесс профилирования. Контролировать - значит, запускать и останавливать процесс, а также создавать "снапшоты" (snapshots), которые тут же становятся доступными для анализа.
 | | Окно управления процессом профилирования |
Снапшот - это мгновенная копия накопленной в процессе профилирования информации. При анализе производительности в снапшот записывается дерево вызовов функций, содержащее информацию о том, сколько раз какие функции были вызваны и откуда и сколько времени потребовалось на их работу. При анализе использования памяти - структура размещения объектов в памяти, информация о том, сколько памяти они занимают и как связаны друг с другом. В общем случае снапшоты могут содержать следующую информацию:
- время, затраченное на выполнение каждой функции;
- количество вызовов каждой функции;
- относительную значимость каждой функции в процентах от полного затраченного времени;
- количество объектов каждого класса;
- размер памяти, выделенный под эти объекты;
- количество удерживаемых объектов и размер удерживаемой памяти.
Содержимое конкретного снапшота, а также полнота и точность содержащейся в нем информации зависят от типа анализа и набора параметров, указанных при запуске dotTrace. Параметров не так много, однако все они оказываются в ряде конкретных случаев чрезвычайно полезными на практике, поэтому имеет смысл вкратце их описать.
dotTrace поддерживает два режима профилирования по производительности - tracing profiling и sampling profiling. В режиме tracing profiling dotTrace получает уведомления о входе в каждую функцию и выходе из нее - время между входом и выходом и есть время выполнения функции. В режиме sampling profiling dotTrace создает отдельный поток, который периодически останавливает все профилируемые потоки и анализирует их стек вызовов. Режим sampling profiling менее точен, чем tracing profiling, и не позволяет точно подсчитывать количество вызовов функций, зато он более быстрый и практически не тормозит работу анализируемых приложений.
Подсчет времени выполнения функций в dotTrace может выполняться в двух режимах: Wall time и Thread time. В режиме Wall time время подсчитывается по таймеру, общему для всех потоков. Этот таймер не зависит от состояния потоков, так что время выполнения функции продолжает увеличиваться даже тогда, когда поток, в котором выполняется функция, находится в режиме ожидания. В режиме Thread time время подсчитывается по таймеру, связанному с потоком. Если поток приостанавливается, то таймер также приостанавливается и время работы функции не увеличивается.
Профилирование по памяти в dotTrace может вестись двумя способами. Во-первых, в любой момент можно создать дамп памяти, полностью отражающий текущую структуру объектов в памяти. Во-вторых, можно провести анализ в Difference mode - режиме различий, - когда в течение заданного временного интервала dotTrace будет записывать все изменения, происходящие в памяти. После завершения анализа можно будет посмотреть, сколько и каких объектов за это время добавилось, сколько и каких было удалено и сколько при этом памяти было потрачено и освобождено.
dotTrace поддерживает возможность запрета встраивания inline-функций Just-in-Time (JIT)-компилятором .Net. При этом производительность приложения, естественно, существенно снизится, зато можно будет получить снапшоты, содержащие информацию о всех без исключения вызовах функций. В режиме tracing profiling dotTrace записывает информацию о всех попытках встраивания функций, которую при анализе снапшота можно будет просмотреть.
Как известно, в Microsoft Net деструкторы объектов вызываются "сборщиком мусора" и время их вызова не определено, поэтому очистка выделенных ресурсов обычно производится с помощью функции Dispose(). Эту функцию необходимо вызывать явно - ее автоматический вызов в деструкторе ведет к снижению производительности приложения и снижает эффективность использования памяти. dotTrace имеет режим, позволяющий при профилировании по памяти собирать информацию об отработанных (финализированных) объектах. При использовании этого режима пользователь, при анализе снапшота, будет иметь возможность просмотреть все объекты, для которых функция Dispose() вызывалась в деструкторе.
Даже для небольших по объему приложений структура данных, сохраняемых в снапшотах, может быть очень сложной, а объем сохраняемой информации - значительным. JetBrains dotTrace предоставляет в распоряжение пользователя мощный набор средств для работы со снапшотами, позволяющих варьировать способы и детальность представления информации, выполнять поиск и фильтрацию данных, автоматически находить "узкие" места в коде и сравнивать результаты анализа снапшотов между собой.
 | | Просмотр данных снапшота при профилировании по производительности |
Интерфейс главного окна JetBrains dotTrace позволяет открывать сразу несколько снапшотов - каждый на отдельной вкладке. Окно для просмотра снапшота строится по следующей схеме. Слева отображается список доступных способов представления информации и подсказка. В центре тем или иным способом отображается дерево вызовов функций или структура данных в памяти. Снизу показан исходный код программы, связанный с выбранной функцией или объектом.
Само окно может содержать одну или несколько вкладок - на первой вкладке отображается полная структура данных, сохраненных в снапшоте, на дополнительных вкладках - часть данных, выбранная пользователем.
JetBrains dotTrace поддерживает множество различных способов отображения информации - views. Например, список объектов в памяти можно посмотреть, сгруппировав их по пространствам имен, по названиям классов или в виде дерева функций, в котором каждой функции сопоставлен список созданных при ее вызове объектов. В свою очередь, дерево вызовов функций можно просматривать в виде дерева, а можно - в виде списка. Отображение в виде списка очень удобно, когда вам, например, требуется определить, какие функции вызывались чаще всего.
JetBrains dotTrace поддерживает возможность открыть отдельную вкладку для выбранной функции, объекта или группы объектов. При этом время выполнения данной функции принимается за 100%, так что наглядно видно, сколько процентов времени занимает выполнение каждой функции, вызываемой в контексте выбранной. При открытии на отдельной вкладке информации об объекте у пользователя появляется ряд дополнительных возможностей по просмотру информации о ссылках, связанных с данным объектом. Например, можно посмотреть список объектов, которые ссылаются на выбранный объект, и список объектов, на которые ссылается он сам.
Фильтры позволяют удобно сужать количество просматриваемой информации. В частности, установленный по умолчанию фильтр System.*,Microsoft.* позволяет скрыть в дереве вызова функций все системные вызовы функций, происходящие в недрах .Net и тем самым отобразить дерево в существенно более компактном виде. К сожалению, фильтрация поддерживается только при профилировании производительности - при профилировании памяти фильтры не работают.
Для аналогичных целей в dotTrace применяются также средства "фолдинга" (folding) - свертки, применяемые для отображения рекурсивных и фильтрованных вызовов. Например, при рекурсии полное дерево рекурсивных вызовов может быть очень громоздким, полным однотипных структур. Свертка позволяет отобразить его в компактном виде, когда повторяющиеся участки дерева показаны всего один раз и для каждой функции указано, сколько раз за время рекурсивного вызова она была вызвана. При фильтрации свертка используется, чтобы включить или отключить показ той части дерева вызовов, которая скрыта по условиям фильтра.
Надо отдать должное разработчикам JetBrains dotTrace - интерфейс программы сделан очень удачно, детально проработан и содержит множество приятных и полезных "мелочей". Например, удобный поиск имени функции, организованный в виде быстрого фильтра. Легенда с расшифровкой значений всех иконок, задействованных в окне просмотра данных. Компактное расположение двух рядов вкладок, увеличивающее рабочую область. Возможность скопировать выбранный участок дерева вызовов функций или объектов в буфер обмена в текстовом виде. В результате работать с JetBrains dotTrace по-настоящему удобно.
Работать с dotTrace можно не только через пользовательский интерфейс, но и программно - dotTrace предоставляет API, которое позволяет контролировать процесс профилирования прямо из кода анализируемого приложения. Например, такая возможность может оказаться весьма полезной, если какой-то код работает медленно не всегда, а лишь изредка. Тогда в код приложения можно вставить проверку времени выполнения кода и программно делать снапшоты именно в тех случаях, когда код срабатывает медленно.
Режим запуска dotTrace через командую строку также реализован, но в этом случае dotTrace позволяет профилировать приложения только по производительности. Для Windows-приложения снапшот записывается по окончании работы приложения, для веб-приложения - по прошествии заданного интервала времени после запуска.
dotTrace интегрируется с Microsoft Visual Studo 2003/2005/2008 - при наличии pdb-файлов становится возможным просмотреть исходный код функции или класса, выбранного в dotTrace, а также открыть файл в студии. Если у вас дополнительно установлена программа JetBrains ReSharper, то
вы сможете прямо из студии запускать профилирование выбранных юнит-тестов.
Более полное представление о функционале dotTrace можно получить, обратившись к документации, которая сделана очень добротно. Кроме того, на сайте разработчиков имеется набор роликов, демонстрирующих работу dotTrace, и любопытная статья, в которой изложены принципы работы с программой.
|