Какие варианты оптимизации приложения существуют кроме горизонтального и вертикального масштабирования?
Что проверяют
Умеете ли вы ускорять код и систему до покупки железа и начинаете ли с измерений. Следом обычно просят рассказать, как вы находили узкое место в реальном проекте и что получили.
Как отвечать
Принцип: оптимизируют то, что показал профайлер, а не то, что кажется медленным. Дальше по слоям:
- профилирование:
cProfileдля общей картины,py-spyснимает профиль с работающего процесса без перезапуска,line_profilerпострочно,tracemallocили memray для памяти; - база данных: самый частый источник. N+1 в Django ORM решают
select_relatedиprefetch_related, в SQLAlchemyselectinloadиjoinedload. ДальшеEXPLAIN ANALYZE, индексы, пагинация; - алгоритмы: поиск в
listэто O(n), вsetиdictO(1), генераторы вместо списков на больших потоках; - кэширование:
functools.lru_cacheв процессе, Redis между процессами, HTTP-кэш и CDN; - I/O и CPU по-разному: ожидание сети ускоряет
asyncioили пул потоков, вычисления из-за GIL выносят вProcessPoolExecutor, векторизуют на NumPy или переписывают горячий участок на Cython или Rust через PyO3; - фоновые задачи: всё, что не нужно в ответе, уходит в очередь, например Celery;
- окружение: Python 3.11 в среднем примерно на четверть быстрее 3.10 по бенчмаркам pyperformance,
orjsonбыстрее стандартногоjson.
Усилит ответ своя история: что тормозило, чем нашли, что поменяли и насколько сократилось время ответа. Цифры называйте из своих замеров, а не круглые.
Где спотыкаются
Оптимизируют без замеров: переписывают цикл на comprehension и выигрывают миллисекунды, пока запрос в базу идёт секунду.
Предлагают потоки для CPU-задач. В CPython с GIL они ускоряют только I/O, вычисления идут по очереди.
Кэшируют без стратегии инвалидации. Пользователи видят устаревшие данные, а functools.cache на функции с множеством уникальных аргументов растёт в памяти без ограничений.