Оптимизация приложений . NET Framework . Интенсивное выделение памяти в приложениях часто влечет за собой значительные накладные расходы па сборку мусора. Выделение памяти в среде выполнения CLR является недорогой операцией, но ее освобождение может сопровождаться значительными накладными расходами. По этой причине группы небольших методов, выделяющих большие объемы памяти, могут отнимать совсем немного процессорного времени и быть практически незаметны в отчете профилировщика времени, но при этом вызывать значительные задержки на сборку мусора в случайных точках выполнения приложения. В своей практике мы встречали приложения, где память выделялась без должного внимания, и нам удавалось увеличивать их производительность - иногда в 1. Для профилирования выделения памяти мы будем использовать два профилировщика - вездесущий профилировщик Visual Studio, поддерживающий режим профилирования выделения памяти, и профилировщик CLR Profiler - самостоятельный и бесплатный инструмент. К сожалению, оба инструмента часто оказывают значительное влияние на производительность приложений, интенсивно использующих динамическую память, потому что для каждой операции выделения памяти профилировщик выполняет последовательность действий по сохранению информации для последующего составления отчетов.
Тем не менее, результаты могут оказаться настолько ценными, что даже 1. Профилировщик выделения памяти Visual Studio. Профилировщик Visual Studio способен собирать информацию об операциях выделения памяти и жизненном цикле объектов (которые освобождаются сборщиком мусора) в обоих режимах, дискретном и инструментированном.
В дискретном режиме профилировщик собирает информацию о выделении памяти в приложении в целом. В инструментированном режиме информация собирается только из инструментированных модулей. Для экспериментов с профилировщиком Visual Studio вы можете использовать приложение Jack. Compiler. exe из исходников к этой статье. В мастере настройки профилировщика производительности выберите радиокнопку . NET memory allocation (Выделение памяти . NET). В конце сеанса профилирования, в представлении Summary (Сводка), будут показаны функции, выделившие памяти больше всего: В представлении Functions для каждого метода будет указано количество объектов и количество байтов памяти, выделенных методом (как обычно, включительные и исключительные значения).
В представлении Function Details (Сведения о функции) будет представлена информация о вызывающих и вызываемых функциях, а также указаны строки кода с объемами выделенной ими памяти в поле слева: Но самая интересная информация содержится в представлении Allocation (Выделение), показывающем, какие ветви в стеке вызовов выделили памяти больше всего: Позже мы узнаем, насколько важно отказаться от использования временных объектов, и обсудим феномен «кризиса среднего возраста» объектов, оказывающего существенное влияние на производительность, который проявляется в способности объектов переживать несколько циклов сборки мусора. Идентифицировать наличие этого явления в приложении можно с помощью представления Object Lifetime (Жизненный цикл объектов), сообщающем, в каком поколении объекты были утилизированы. Это представление поможет увидеть, имеются ли объекты, пережившие слишком много циклов сборки мусора.
На рисунке ниже можно видеть, что все объекты строк, созданные приложением (и занимающие более 1 Гбайта памяти!) были утилизированы в нулевом поколении, а это означает, что ни одному из них не удалось прожить дольше одного цикла сборки мусора: Хотя отчеты о выделении памяти, генерируемые профилировщиком Visual Studio, отличаются богатством информации, в них все же имеются некоторые недостатки. Например, трассировка стека вызовов с целью сгруппировать операции выделения памяти по типам объектов занимает достаточно много времени, если выделение памяти производится во множестве разных мест (что всегда верно для строк и массивов байтов). Профилировщик CLR Profiler поддерживает несколько дополнительных особенностей, делающих его ценной альтернативой профилировщику Visual Studio. CLR Profiler. Профилировщик CLR Profiler - это отдельный инструмент профилирования, не требующий установки и занимающий менее 1 Мбайта дискового пространства.
- NET Memory allocation в
- NET memory allocation (Р’С. NET Memory Profiler - Р
- Профилировщик SciTech.NET Memory Profiler - еще один коммерческий инструмент, предназначенный для выявления утечек памяти.
Как дополнительное преимущество, он распространяется с исходными текстами, которые наверняка заинтересуют тех, кто пожелает заняться созданием собственных инструментов, использующих CLR Profiling API. Он способен подключаться к выполняющимся процессам (если используется версия CLR не ниже 4. Пользоваться профилировщиком CLR Profiler очень просто - запустите профилировщик, щелкните на кнопке Start Application (Запустить приложение), выберите приложение для профилирования и дождитесь появления отчета - богатство информации для кого- то может оказаться ошеломляющим. Мы рассмотрим здесь некоторые отчеты профилировщика, а полное руководство вы найдете в документе CLRProfiler. Как обычно, для экспериментов с профилировщиком вы можете использовать пример приложения Jack. Compiler. exe или свое приложение.
На рисунке ниже показан главный отчет, появляющийся после завершения профилируемого приложения. Он содержит основные сведения, касающиеся выделения памяти и сборки мусора.
Далее из этого отчета можно пойти в нескольких направлениях. Мы сконцентрируемся на исследовании источников выделения памяти, чтобы понять, в каком месте приложения создается больше всего объектов (этот отчет напоминает представление Allocation профилировщика Visual Studio). Мы могли бы заняться исследованием сборки мусора, чтобы узнать, какие объекты утилизируются. Наконец, можно было. Щелчок на кнопке Histogram (Гистограмма) рядом с полем Allocated bytes (Выделено байтов) или Final heap bytes (Конечный объем кучи в байтах) выведет гистограмму по типам объектов, сгруппированных по размерам. Эта гистограммы можно использовать для выявления больших и малых объектов, а также объектов, создаваемых чаще других. На рисунке ниже показана гистограмма для всех объектов, создаваемых нашим примером приложения: Каждый столбик представляет объекты определенного размера.
Легенда справа содержит общее число созданных экземпляров каждого типа и объем выделенной памяти в байтах. Щелчок на кнопке Allocation Graph (График выделения) откроет отчет о выделении памяти в дереве стека вызовов для всех объектов в приложении. Информация в этом отчете сгруппирована так, чтобы легко можно было перейти от методов, выделивших больше всего памяти, к отдельным типам объектов и посмотреть, какие методы создали больше всего экземпляров этих типов.
На рисунке ниже показана малая часть графика выделения памяти, начиная от метода Parser. Parse. Statement(), выделившего (включительно) 3. Мбайт памяти и до различных методов, вызываемых им. Она позволяет быстро обнаружить долгоживущие и временные объекты, что может пригодиться для борьбы с явлением «кризиса среднего возраста» объектов C#.
Щелчок на кнопке Objects by Address (Объекты по адресу) отобразит области управляемой динамической памяти в виде слоев; чем ниже слой, тем он старше. Подобно археологу вы можете погружаться в более глубокие слои и выяснять, какие объекты занимают память в вашем приложении. Этот отчет можно также использовать для диагностики фрагментации динамической памяти: Метки слева - это адреса, метки «gen 0» и «gen 1» - это подразделы динамической памяти. Наконец, щелчок на кнопке Time Line (График времени) в разделе Garbage Collection Statistics (Статистика сборки мусора) откроет отчет с информацией об отдельных циклах сборки мусора и их влиянии на динамическую память приложения: Отметки на нижней оси представляют отдельные циклы сборки мусора, а в области графика изображается состояние управляемой динамической памяти. После сборки мусора объем используемой памяти резко уменьшается, а затем постепенно возрастает, до следующего цикла. В данном случае объем используемой памяти (после сборки мусора) остается постоянным, из чего следует, что в этом приложении отсутствуют утечки памяти. Этот график можно использовать для определения типов утилизируемых объектов, и получения представления о том, как изменяется распределение динамической памяти после сборки мусора.
С его помощью можно также выявлять утечки памяти, когда сборщик мусора освобождает недостаточно памяти, из- за того, что приложение продолжает удерживать все увеличивающееся количество объектов. Графики и гистограммы выделения памяти - весьма полезные инструменты анализа, но иногда важнее бывает выявить ссылки между объектами, а не объемы выделяемой памяти в разных методах. Например, когда в приложении обнаруживаются утечки управляемой памяти, очень полезно пройтись по динамической памяти, чтобы найти категории объектов, занимающие наибольшие объемы памяти и узнать, какие объекты на них ссылаются, мешая сборщику мусора утилизировать их. Пока профилируемое приложение выполняется, щелкните на кнопке Show Heap now (Показать кучу сейчас), чтобы сгенерировать дамп динамической памяти для последующего исследования с целью классификации ссылок между объектами.
На рисунке ниже показан отчет профилировщика сразу с тремя дампами динамической памяти, расположенными друг над другом, показывающий увеличение количества объектов типа byte. Коммерческие инструменты, которые мы рассмотрим далее, предлагают более богатые возможности, включая автоматические средства обнаружения наиболее типичных источников утечек памяти, разнообразные фильтры и возможности более сложной группировки информации. Поскольку большинство из этих инструментов не сохраняют информацию о каждом объекте, размещенном в динамической памяти, и не сохраняют информацию о выделении памяти в разных методах, они имеют более низкие накладные расходы, что само по себе является большим преимуществом. Коммерческие профилировщики памяти. В этом разделе мы познакомимся с двумя коммерческими профилировщиками памяти, специализирующимися на визуализации состояния динамической памяти и выявлении источников утечек памяти.
SciTech.NET Memory Profiler v4.0.114 Год/Дата Выпуска: 2011 Версия: 4 Build 114 Разработчик: SciTech Software Сайт разработчика: http.
NET Reflector VSPro Рё ANTS Memory Profiler.