TGViewer
Сергей Озеранский Сергей Озеранский @sergeiozeranskii · 2.35K subscribers
Post #614 571
Возьмем Python-сервис в Kubernetes. Как правило на старте контейнера может проявляться спайк потребления ресурсов (CPU в основном) и даже может быть тротлинг (если у пода задан CPU limit), а поды начинают отвечать на health-проверки только через 6-7 секунд после старта, а может и того больше или уйти в crashloop.

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

Причина в том, что в образе нет байткода после сборки. Официальный образ python удаляет файлы .pyc при сборке, чтобы уменьшить размер, поэтому стандартная библиотека (stdlib) лежит в нем без байткода.

Poetry и uv по умолчанию не компилируют зависимости при установке. Часто в Dockerfile еще задан PYTHONDONTWRITEBYTECODE=1 и приложение работает не от root. Тогда Python не может сохранить скомпилированные модули, и каждый процесс при каждом старте заново компилирует их из исходников. В сервисе среднего размера это несколько тысяч модулей.

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

В базовом этапе, от root, компилируем стандартную библиотеку:

RUN python -m compileall -q -j0 "$(python -c 'import sysconfig; print(sysconfig.get_path("stdlib"))')"


В финальном этапе компилируем приложение и зависимости:

RUN python -m compileall -q -j0 app/ .venv/


В моих замерах время импорта приложения сократилось вдвое, под в кластере стал готов вдвое быстрее. За первые 90 секунд после старта под израсходовал на 45% меньше CPU, память после старта снизилась на 6%. В установившемся режиме потребление не меняется: байткод влияет только на импорт. Образ вырастает примерно на 4%.

Изменение безопасно. Python сравнивает .pyc с исходным файлом и не использует устаревший байткод, поэтому ошибка в этом шаге не приведёт к выполнению старого кода. Документация uv рекомендует компилировать байткод в продовых образах. У Poetry для этого есть флаг poetry install --compile. pip компилирует байткод по умолчанию.

Одно ограничение: compileall возвращает ошибку, если в каком-нибудь пакете окажется файл с синтаксисом, который текущая версия Python не разбирает. Сборка тогда упадет. pip и poetry install --compile такие файлы пропускают.

Проверить свой образ можно так:


docker run --rm --entrypoint sh <image> -c \
'find / -name "*.py" -path "*python3*" | wc -l; find / -name "*.pyc" -path "*python3*" | wc -l'


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

Изменение ускоряет запуск контейнера и уменьшает всплеск CPU при старте. Поэтому при настройке requests и limits в Kubernetes можно закладывать меньше запаса на старт приложения.
  • 🔥 13
  • 👍 3
  • ❤ 2
  • ⚡ 1
More from @sergeiozeranskii
  1. Sep 24, 2026Еще немного про ускорения. На этот раз про тесты, а точнее про coverage (Python). Библиоте…
  2. Sep 24, 2026Обнаружил, что агенты Claude Code в разных сессиях умеют общаться между собой. У меня сейч…
  3. Sep 23, 2026Сегодня случилось страшное. То, чего я никак не ожидал. За все годы на MacBook со мной так…
  4. Sep 17, 2026Я вот не понимаю, зачем люди идут в OSS и контрибьютят на отвали. Ценности в этом ноль для…
  5. Sep 17, 2026Помните про https://github.com/ozeranskii/httptap? Я писал о нем давно еще - > тут. Наклеп…
  6. Sep 17, 2026Поломали или у меня поломалось? Как у вас?
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →