Каким образом можно провести профилирование использования памяти в работающем приложении на FastAPI, написанном на Python?

У меня есть приложение на FastAPI, которое работает с помощью Gunicorn, и используется несколько рабочих процессов (воркеров). В настоящее время приложение обслуживает около 50 пользователей одновременно. Со временем наблюдается значительное потребление памяти сервером, которое достигает значений в 3-10 Гб на воркер. Если я уменьшаю количество воркеров, память все равно полностью используется. Как я могу определить, на что именно расходуется память в моем приложении?
  • 25 ноября 2024 г. 20:03
Ответы на вопрос 2
Профилирование использования памяти в приложении на FastAPI, работающем на Python, может помочь вам выявить узкие места и утечки памяти. Вот несколько шагов и инструментов, которые вы можете использовать для этой цели:

### 1. Используйте инструменты для профилирования памяти

- **objgraph**: Этот модуль позволяет вам визуализировать объекты и их взаимосвязи в памяти. Он поможет вам увидеть, какие типы объектов занимают больше всего памяти.

  ```python
  import objgraph

  # В вашем коде, например, в обработчике после обработки запроса
  objgraph.show_most_common_types(limit=10)
  objgraph.show_growth()
  ```

- **memory-profiler**: Этот пакет позволяет отслеживать использование памяти построчно в вашем коде.

  ```bash
  pip install memory-profiler
  ```

  Используйте декоратор `@profile` для функций, которые вы хотите проанализировать:

  ```python
  from memory_profiler import profile

  @profile
  def my_function():
      ...
  ```

- **tracemalloc**: Встроенный модуль Python, который позволяет отслеживать распределение памяти. Он доступен с Python 3.4 и выше.

  ```python
  import tracemalloc

  tracemalloc.start()

  # Ваша логика, которую вы хотите проанализировать

  snapshot = tracemalloc.take_snapshot()
  top_stats = snapshot.statistics('lineno')

  print("[Top 10 Memory Usage]")
  for stat in top_stats[:10]:
      print(stat)
  ```

### 2. Анализируйте использование памяти

- **Логируйте данные о памяти**: Вы можете добавить в ваше приложение логирование текущего использования памяти. Это можно сделать с помощью модуля `psutil`.

  ```python
  import psutil
  import os

  process = psutil.Process(os.getpid())
  print(f"Memory usage: {process.memory_info().rss / 1024 ** 2} MB")  # RSS в МБ
  ```

- **Профилирование по времени**: Сравните использование памяти на разных этапах выполнения ваших обработчиков. Это поможет вам увидеть, где происходит наибольшее увеличении использования памяти.

### 3. Обратите внимание на потенциал утечек памяти

- Проверьте, не остаются ли ссылки на объекты, которые больше не нужны, например, в глобальных переменных или в кэшах.
- Используйте weakref (слабые ссылки) для объектов, которые могут быть не нужны.

### 4. Тестирование нагрузки

- Проведите нагрузочное тестирование (например, с помощью Locust или Apache Benchmark) для моделирования многопользовательской среды и отслеживания использования памяти в зависимости от нагрузки.

### 5. Запуск с ограничением по памяти

- Можно запустить ваши воркеры Gunicorn с ограничением по памяти, чтобы предотвратить исчерпание ресурсов сервера.

### 6. Мониторинг и логирование

- Используйте системы мониторинга, такие как Prometheus и Grafana, чтобы отслеживать использование ресурсов сервера в реальном времени. Это поможет вам обнаруживать проблемы до их серьезного воздействия.

### Заключение

Профилирование использования памяти в FastAPI может требовать времени и терпения, но с помощью указанных инструментов и методов вы сможете выявить проблемные места и оптимизировать использование памяти в вашем приложении. После внесения изменений продолжайте мониторинг, чтобы убедиться, что проблемы решены.
Может тебе поможет `pyinstrument` или `scalene` найти проблему. На первый взгляд выглядит как утечка памяти.
Похожие вопросы