Что такое Object Pool и когда он оправдан?
Порождающие паттерны
Object Pool держит набор заранее созданных дорогих объектов и выдаёт их во временное пользование (acquire/release) вместо создания и уничтожения на каждый запрос.
Когда оправдан
- Создание дорого в абсолютных цифрах: соединение с БД — это TCP + TLS + аутентификация, единицы-десятки миллисекунд; потоки, воркеры, GPU-буферы.
- Нужен лимит на ресурс: пул на 10 соединений не даст тысяче параллельных запросов упереться в
max_connectionsPostgres (по умолчанию 100). - Игры и анимации: пули и частицы создаются сотнями в секунду, пул убирает паузы GC и просадки FPS.
Когда вреден
- Для мелких объектов в JS, Java, Go: поколенческий GC выделяет короткоживущие объекты почти бесплатно, а пул продлевает им жизнь и переносит их в старшее поколение.
- Добавляет ручное управление жизненным циклом — ровно то, от чего избавляет GC.
Типичные ошибки
- Объект не вернули → пул исчерпан, запросы висят. Нужны
try/finallyи таймаут на acquire. - Не сбросили состояние → утечка между клиентами: незакрытая транзакция,
SET search_path, данные прошлого пользователя. - Двойной release → один объект выдан двум клиентам одновременно.
- Мёртвые соединения: пул должен валидировать объект перед выдачей или по таймеру.
- Пул соединений больше нужного: размер считают от ядер БД (
cores * 2 + effective_spindle_count), а не от числа клиентов.
Коротко для собеседования
Object Pool переиспользует дорогие объекты вроде соединений с БД и заодно ограничивает их число. Для мелких объектов он вреден из-за GC, а в работе с пулом главное — всегда возвращать объект в finally и сбрасывать его состояние.