> С чем именно приходилось бороться в производительности (Python)
Уровень: senior · Роль: backend · Язык: Python · Категория: Технические вопросы
Компании: Сбер
Стек: Python
> Пример ответа
Короткий ответ
Основные проблемы производительности в Python-бэкенде: CPU-bound задачи из-за GIL, неэффективные ORM-запросы (N+1, лишние выборки), блокирующий I/O, рост потребления памяти, медленная сериализация/десериализация, неоптимальные алгоритмы и структуры данных, а также проблемы с кэшированием и конкурентностью. На практике чаще всего приходится бороться с запросами к БД и неэффективным использованием циклов и коллекций.
Подробное объяснение
В Python производительность упирается в несколько фундаментальных ограничений:
- GIL - не даёт использовать несколько ядер для CPU-bound кода в рамках одного процесса. Решения: multiprocessing, asyncio для I/O-bound, C-расширения, переписывание горячих участков на Cython/C.
- ORM-запросы - самый частый источник проблем. N+1 запросов, выборка лишних колонок, отсутствие индексов, тяжёлые JOIN'ы, материализация больших наборов в память.
- Блокирующий I/O - синхронные вызовы к внешним сервисам, БД, файловой системе. Решение: async/await, пулы потоков, connection pooling.
- Сериализация - JSON, pickle, msgpack. На больших объёмах данных это становится узким местом. Решение: orjson, ujson, protobuf.
- Память - утечки, большие объекты, неэффективные структуры данных. Решение: профилирование памяти, использование
__slots__, генераторы вместо списков. - Алгоритмическая сложность - использование O(n²) там, где можно O(n log n), неверный выбор коллекций (list вместо set для проверки вхождения).
- Кэширование - отсутствие кэша, неверная стратегия инвалидации, слишком маленький TTL, кэш-промахи.
На практике
Начинаю с профилирования: cProfile, py-spy, memory_profiler, tracemalloc. Затем смотрю на:
- Запросы к БД - включаю логирование медленных запросов, проверяю EXPLAIN, добавляю индексы, переписываю на агрегации в SQL вместо Python-циклов.
- Горячие функции - выношу в отдельные модули, оптимизирую алгоритмы, заменяю рекурсию на итерации.
- I/O - перевожу на asyncio, использую aiohttp, asyncpg, aioredis. Для синхронных библиотек - ThreadPoolExecutor.
- Сериализацию - заменяю стандартный json на orjson, для внутренних сервисов - protobuf или msgpack.
- Память - ищу утечки через tracemalloc, оптимизирую хранение данных, использую слабые ссылки.
Типичный пример: сервис, который обрабатывает 100k запросов в час, упирается в N+1 запросы ORM. Решение - select_related/prefetch_related, или переход на сырые SQL-запросы для сложных выборок.
Пример кода
PYTHON# Плохо: N+1 запросовdef get_orders_with_items(user_id):orders = Order.objects.filter(user_id=user_id)result = []for order in orders:items = order.items.all() # запрос на каждый orderresult.append((order, items))return result# Хорошо: один запрос с prefetch_relateddef get_orders_with_items_optimized(user_id):orders = Order.objects.filter(user_id=user_id).prefetch_related('items')return [(order, order.items.all()) for order in orders]
PYTHON# Плохо: сериализация стандартным jsonimport jsondata = [{"id": i, "name": f"item_{i}"} for i in range(100000)]serialized = json.dumps(data)# Хорошо: orjson в 2-3 раза быстрееimport orjsonserialized = orjson.dumps(data)
Как отвечать на собеседовании
Структурируй ответ по категориям: CPU, I/O, память, БД. Назови конкретные инструменты профилирования, которые используешь. Приведи реальный кейс из практики: что было узким местом, как диагностировал, что сделал, какой прирост получил. Покажи понимание trade-off: например, asyncio не решает CPU-bound проблемы, а multiprocessing добавляет overhead на межпроцессное взаимодействие. Упомяни, что сначала всегда профилируешь, а не оптимизируешь вслепую.
Что проверяет интервьюер
- Понимание фундаментальных ограничений Python (GIL, глобальная интерпретация).
- Умение системно подходить к диагностике: профилирование, метрики, логирование.
- Знание инструментов: cProfile, py-spy, memory_profiler, EXPLAIN, slow query log.
- Практический опыт: конкретные решения, а не теоретические рассуждения.
- Способность оценивать trade-off: скорость разработки vs производительность, сложность vs выгода.
- Понимание, что оптимизация - это итеративный процесс с измерением результата.
Типичные ошибки
- Начинать оптимизировать без профилирования - "оптимизация вслепую".
- Сводить всё к GIL и сразу предлагать multiprocessing, не проверив, что проблема действительно CPU-bound.
- Игнорировать БД как источник проблем - большинство узких мест именно там.
- Предлагать asyncio для CPU-bound задач.
- Не учитывать память: оптимизировать по времени, но забывать про потребление RAM.
- Использовать преждевременную оптимизацию: усложнять код ради гипотетического прироста.
- Не измерять результат после изменений - без бенчмарков нельзя подтвердить улучшение.
> Похожие задачи по Python
Планируешь ли пересматривать оценки задач
Насколько доволен своей оценкой задач
Какая должна быть длина короткой ссылки, чтобы избежать коллизий при заданной нагрузке и времени жизни
Как оценить необходимое дисковое пространство для хранения сокращенных ссылок с учетом нагрузки и времени жизни
> Похожие задачи по backend
Планируешь ли пересматривать оценки задач
Насколько доволен своей оценкой задач
Какая должна быть длина короткой ссылки, чтобы избежать коллизий при заданной нагрузке и времени жизни
Как оценить необходимое дисковое пространство для хранения сокращенных ссылок с учетом нагрузки и времени жизни
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью