УДК 004.4

Профилирование асинхронного FastAPI приложения

Пантюк Тимофей Александрович – студент факультета системы управления, информатики и электроэнергетики Московского авиационного института.

Аннотация: Стремительное развитие асинхронных веб-технологий ставит перед разработчиками задачу постоянного повышения производительности веб-приложений. В этом контексте, особенно важной становится задача профилирования - процесса сбора данных о работе программы для выявления узких мест в производительности. Данная статья освещает проблематику профилирования асинхронных запросов в среде FastAPI, выделяя особенности и ограничения использования традиционного инструмента профилирования cProfile для асинхронного кода. В качестве альтернативы представлен инструмент pyinstrument, который благодаря поддержке асинхронности и статистического профилирования позволяет получать более точную картину производительности приложений. Статья подробно рассматривает процесс интеграции pyinstrument с FastAPI, а также демонстрирует преимущества данного подхода на примере анализа производительности асинхронных запросов. Таким образом, текст предлагает разработчикам комплексный взгляд на методы и инструменты профилирования, необходимые для оптимизации асинхронных веб-приложений.

Ключевые слова: профилирование приложений, FastAPI, асинхронное программирование, cProfile, pyinstrument, оптимизация производительности.

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

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

FastAPI, современный высокопроизводительный фреймворк для создания API с поддержкой асинхронности на Python, представляет собой идеальную основу для разработки веб-приложений, требующих высокой производительности и эффективности обработки запросов. Благодаря своим преимуществам, таким как скорость разработки, простота изучения и готовность к использованию в продакшене, FastAPI завоевал популярность среди разработчиков. Однако для полного раскрытия потенциала асинхронных приложений, созданных с его помощью, необходимо глубокое понимание того, как профилировать и оптимизировать их работу.

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

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

Принцип работы cProfile заключается в том, что он "прослушивает" все вызовы функций в программе, записывая информацию о времени выполнения и числе вызовов каждой из них. Это позволяет разработчикам получать детализированные отчеты о производительности, выявлять узкие места в приложении и принимать информированные решения об оптимизации.

Одним из ключевых преимуществ cProfile является его способность работать с любыми Python-приложениями "из коробки", без необходимости модификации или дополнительной настройки кода. Это делает его доступным и удобным инструментом для быстрого анализа производительности.

Тем не менее, при работе с асинхронным кодом, особенно в современных асинхронных фреймворках вроде FastAPI, разработчики могут столкнуться с определенными ограничениями cProfile. Эти ограничения связаны с особенностями асинхронного выполнения и могут существенно исказить результаты профилирования, не давая полной картины производительности приложения. В процессе анализа данных профилирования асинхронного приложения можно столкнуться с определенными особенностями и ограничениями, которые делают традиционные методы менее эффективными. Примером этого могут служить результаты, полученные при использовании инструмента cProfile для изучения производительности асинхронных запросов. Анализируя данные, можно заметить, что количество вызовов отдельных асинхронных функций и их связь с остальным кодом не всегда отражает реальную картину.

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

Такие результаты могут сбивать с толку, поскольку асинхронная функция при каждом вызове await временно "выходит" из исполнения, позволяя циклу событий обрабатывать другие задачи. Каждый раз, когда цикл событий возвращает выполнение к асинхронной функции, cProfile интерпретирует это как новый вызов, что приводит к завышенным значениям. Это особенно заметно в случаях, когда функция активно использует операции ввода/вывода, такие как запросы к базе данных или сетевые запросы.

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

Pyinstrument — это статистический профайлер, в отличие от детерминированного cProfile.

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

Кроме того, pyinstrument поддерживает профилирование асинхронного кода на Python. Pyinstrument может профилировать асинхронные программы, использующие async и await. Эта поддержка работает за счет отслеживания контекста выполнения с помощью встроенного модуля contextvars.

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

Для регистрации промежуточного программного обеспечения профилирования (которое активируется, если установлена настройка PROFILING_ENABLED) используется декоратор FastAPI.middleware. Это промежуточное ПО отвечает за профилирование запроса, если клиент передает аргумент запроса profile=true. (см. рис. 1)

По умолчанию это промежуточное ПО генерирует отчет в формате JSON, совместимом с Speedscope, онлайн-визуализатором интерактивных flamegraph. Однако, если передается аргумент запроса profile_format=html, то вместо этого на диск выгружается простой HTML-отчет.

Рисунок1

Рисунок 1. Код асинхронного профайлера

Процесс профилирования асинхронных приложений на FastAPI подчеркивает специфические вызовы и возможности, связанные с асинхронным программированием. В контексте данной статьи были рассмотрены основные ограничения cProfile при работе с асинхронным кодом и представлен pyinstrument как более адаптированный инструмент для этих целей. Использование pyinstrument позволяет разработчикам получать детализированную картину выполнения асинхронных запросов, улучшая понимание производительности приложений и выявляя потенциальные узкие места в коде.

Через пример интеграции pyinstrument с FastAPI было показано, как промежуточное программное обеспечение может служить мостом для сбора профилировочных данных, облегчая анализ и оптимизацию производительности. Эта интеграция подчеркивает важность выбора подходящих инструментов и методик при работе с современными асинхронными фреймворками.

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

Список литературы

  1. FastAPI официальная документация. [Электронный ресурс]. URL: https://fastapi.tiangolo.com/ (дата обращения: 17.03.2024).
  2. Python официальная документация по cProfile. [Электронный ресурс]. URL: https://docs.python.org/3/library/profile.html#module-cProfile (дата обращения: 17.03.2024).
  3. Pyinstrument официальная документация. [Электронный ресурс]. URL: https://pyinstrument.readthedocs.io/en/latest/ (дата обращения: 17.03.2024)
  4. Карлтон Дж. Асинхронное программирование в Python с использованием asyncio // Python Engineer. 2020. [Электронный ресурс]. URL: https://python-engineer.com/posts/asyncio/ (дата обращения: 17.03.2024).
  5. Стивенсон С. Оптимизация производительности Python-приложений: от профилирования до ускорения // Developer. 2019. [Электронный ресурс]. URL: https://developer.com/python/performance-optimization/ (дата обращения: 17.03.2024).
  6. Вильямс Л., Кеннеди Б. Асинхронное веб-программирование в Python с FastAPI и Pydantic // Real Python. 2021. [Электронный ресурс]. URL: https://realpython.com/fastapi-python-web-apis/ (дата обращения: 17.03.2024).