Поделиться через


Пример. Изоляция проблемы с производительностью (C#, Visual Basic, F#)

Используйте средства профилирования для изучения проблем с производительностью и изоляции проблемных областей. В этом примере используется пример приложения с проблемами производительности, чтобы продемонстрировать, как использовать средства профилирования для повышения эффективности. Если вы хотите сравнить средства профилирования, см . раздел "Какой инструмент должен выбрать"?

В этом примере рассматриваются следующие темы:

  • Как использовать средства профилирования Visual Studio для анализа производительности приложений.
  • Как интерпретировать данные, предоставляемые этими средствами, для выявления узких мест производительности.
  • Применение практических стратегий для оптимизации кода, фокусировки на счетчиках .NET, счетчиках вызовов и данных о времени.

Следуйте инструкциям, а затем применяйте эти методы к собственным приложениям, чтобы сделать их более эффективными и экономичными.

Изоляция примера проблемы с производительностью

Пример приложения в этом примере — это приложение ASP.NET, которое выполняет запросы к имитированной базе данных. Пример основан на примере диагностики.

Основная проблема с производительностью примера приложения заключается в неэффективных шаблонах кодирования. Приложение имеет узкие места производительности, что значительно влияет на ее эффективность. Проблема включает следующие симптомы:

  • Низкое использование ЦП: приложение показывает низкое использование ЦП, указывающее, что ЦП не является узким местом.

  • Высокий счетчик потоков ThreadPool: количество потоков относительно высокий и неуклонно растет, предлагая нехватку пула потоков.

  • Медленный ответ приложения: приложение реагирует медленно из-за отсутствия доступных потоков для обработки новых рабочих элементов.

В этом примере рассматриваются эти проблемы, используя средства профилирования Visual Studio для анализа производительности приложения. Понимая, где и как можно улучшить производительность приложения, разработчики могут реализовать оптимизации, чтобы сделать код более быстрым и эффективным. Конечная цель заключается в повышении общей производительности приложения, что делает его более эффективным и экономичным для выполнения.

Задача

Устранение проблем с производительностью в примере приложения .NET представляет несколько проблем. Эти проблемы связаны с сложностью диагностики узких мест производительности. Основные проблемы, связанные с устранением проблем, описанных ниже.

  • Диагностика узких мест производительности: одна из основных проблем заключается в точном определении первопричин проблем с производительностью. Низкое использование ЦП в сочетании с низкой производительностью может иметь несколько факторов, влияющих на производительность. Разработчики должны эффективно использовать средства профилирования для диагностики этих проблем, что требует некоторого понимания того, как работают эти средства и как интерпретировать их выходные данные.

  • Ограничения знаний и ресурсов. Команды могут столкнуться с ограничениями, связанными с знаниями, опытом и ресурсами. Профилирование и оптимизация приложения требуют определенных навыков и опыта, а не все команды могут иметь немедленный доступ к этим ресурсам.

Для решения этих проблем требуется стратегический подход, который объединяет эффективное использование средств профилирования, технических знаний и тщательного планирования и тестирования. В этом исследовании рассматривается руководство разработчиков по этому процессу, предоставляя стратегии и аналитические сведения для преодоления этих проблем и повышения производительности приложения.

Стратегия

Ниже приведено высокоуровневое представление подхода в этом примере:

  • Мы начинаем расследование, просматривая метрики счетчиков .NET при сборе данных о производительности. Как и средство использования ЦП, средство счетчиков .NET в Visual Studio также является хорошей отправной точкой для исследования производительности.
  • Далее для получения дополнительных аналитических сведений, помогающих изолировать проблемы или повысить производительность, рассмотрите возможность сбора трассировки с помощью одного из других средств профилирования. Например, ознакомьтесь с подсчетом вызовов и данными о времени с помощью средства инструментирования .

Для сбора данных требуются следующие задачи:

  • Установка приложения на сборку выпуска.
  • Выберите средство счетчиков .NET в профилировщике производительности (ALT+F2). (Последующие шаги включают инструментирование.)
  • В профилировщике производительности запустите приложение и соберите трассировку.

Проверка счетчиков производительности

При запуске приложения мы наблюдаем счетчики в средстве счетчиков .NET. Для первоначальных исследований некоторые ключевые метрики, чтобы следить за включением:

  • CPU Usage. Просмотрите этот счетчик, чтобы узнать, возникает ли проблема с производительностью с высоким или низким потреблением ЦП. Это может быть ключом к конкретным типам проблем с производительностью. Например:
    • При высокой загрузке ЦП используйте средство использования ЦП для выявления областей, где можно оптимизировать код. В этом руководстве приведено руководство по оптимизации кода для начинающих.
    • При низком использовании ЦП используйте инструментирование, чтобы определить количество вызовов и среднее время функции на основе времени настенные часы. Это может помочь выявить такие проблемы, как состязание или голодание пула потоков.
  • Allocation Rate. Для запросов на обслуживание веб-приложений скорость должна быть достаточно стабильной.
  • GC Heap Size. Просмотрите этот счетчик, чтобы узнать, растет ли использование памяти постоянно и потенциально утечки. Если кажется высоким, используйте один из средств использования памяти.
  • Threadpool Thread Count. Для запросов на обслуживание веб-приложений просмотрите этот счетчик, чтобы узнать, держится ли число потоков устойчивым или растет на стабильном уровне.

Вот пример, показывающий, как низкий, в то время как CPU Usage ThreadPool Thread Count относительно высокий.

Снимок экрана: счетчики, отображаемые в средстве счетчиков .NET.

Постоянно растущее число потоков с низким потреблением ЦП может быть индикатором нехватки пула потоков. Пул потоков вынужден продолжать спиннинг новых потоков. Нехватка пула потоков возникает, когда пул не имеет доступных потоков для обработки новых рабочих элементов и часто вызывает медленное реагирование приложений.

На основе низкой загрузки ЦП и относительно высокого количества потоков и работы с теорией возможного случая нехватки пула потоков переключитесь на использование средства инструментирования.

Изучение количества вызовов и данных о времени

Давайте рассмотрим трассировку из инструмента инструментирования, чтобы узнать больше о том, что происходит с потоками.

После сбора трассировки с помощью средства инструментирования и загрузки его в Visual Studio мы сначала проверим начальную страницу отчета о диагсессии , в котором показаны суммированные данные. В собранной трассировке мы используем ссылку "Открыть сведения " в отчете и выберите "Диаграмма пламени".

Снимок экрана:

Визуализация "Диаграмма пламени" показывает, что QueryCustomerDB функция (показанная желтым цветом) отвечает за значительную часть времени выполнения приложения.

Щелкните правой кнопкой мыши функцию QueryCustomerDB и выберите "Вид" в дереве вызовов.

Снимок экрана: дерево вызовов в инструментировании.

Путь кода с наибольшим использованием ЦП в приложении называется горячим путем. Значок пламени горячего пути (Снимок экрана: значок горячего пути.) может помочь быстро определить проблемы с производительностью, которые могут быть улучшены.

В представлении дерева вызовов видно, что горячий путь включает QueryCustomerDB функцию, которая указывает на потенциальную проблему производительности.

Относительно времени, затраченного на другие функции, значения Self и Avg Self для QueryCustomerDB функции очень высоки. В отличие от Total и Avg Total, самозаверяемые значения исключают время, затраченное на другие функции, поэтому это хорошее место для поиска узких мест производительности.

Совет

Если значения Self были относительно низкими, а не высокими, вероятно, потребуется посмотреть на фактические запросы, вызываемые QueryCustomerDB функцией.

Дважды щелкните QueryCustomerDB функцию, чтобы отобразить исходный код для функции.

public ActionResult<string> QueryCustomerDB()
{
    Customer c = QueryCustomerFromDbAsync("Dana").Result;
    return "success:taskwait";
}

Мы делаем небольшое исследование. Кроме того, мы можем сэкономить время и позволить Copilot делать исследования для нас.

Если мы используем Copilot, выберите Ask Copilot в контекстном меню и введите следующий вопрос:

Can you identify a performance issue in the QueryCustomerDB method?

Совет

Вы можете использовать команды косой черты, такие как /optimize , чтобы помочь сформировать хорошие вопросы для Copilot.

Copilot сообщает нам, что этот код вызывает асинхронный API без использования await. Это шаблон кода синхронизации над асинхронным кодом, который является распространенной причиной голода threadpool и может блокировать потоки.

Для разрешения используйте await. В этом примере Copilot предоставляет следующее предложение кода вместе с объяснением.

public async Task<ActionResult<string>> QueryCustomerDB()
{
    Customer c = await QueryCustomerFromDbAsync("Dana");
    return "success:taskwait";
}

Если возникают проблемы с производительностью, связанные с запросами к базе данных, можно использовать средство базы данных для изучения того, являются ли некоторые вызовы медленнее. Эти данные могут указывать на возможность оптимизации запросов. Руководство, в котором показано, как использовать средство базы данных для изучения проблемы с производительностью, см . в руководстве по оптимизации кода для начинающих. Средство базы данных поддерживает .NET Core с ADO.NET или Entity Framework Core.

Чтобы получить визуализации в Visual Studio для отдельного поведения потока, можно использовать окно Parallel Stacks во время отладки. В этом окне показаны отдельные потоки, а также сведения о потоках ожидания, потоках, которые они ожидают, и взаимоблокировках.

Дополнительные сведения о нехватке пула потоков см. в разделе "Обнаружение голода threadpool".

Следующие шаги

В следующих статьях и блогах содержатся дополнительные сведения, которые помогут вам эффективно использовать средства производительности Visual Studio.