__init_subclass__ и метаклассы: Zero‑allocation DTO без Pydantic под high‑flow RPCКогда RPC-сервис пережевывает миллионы коротких запросов в секунду, каждая лишняя аллокация — боль. Pydantic под капотом создает словари, кэши, трейсы — для обычного API норм, но для high-flow это убивает latency. Типичная ошибка: использовать универсальный DTO, не задумываясь о цене каждого байта.
Проблема лишних оберток
Protobuf-сообщения уже имеют слоты и фиксированный размер. Но после десериализации часто хочется плоский контейнер: DTO без методов, только поля. Наивный dataclass с
__slots__ аллоцирует объект и хранит ссылки, protobuf-обертка — еще один слой.Решение: метакласс и
__init_subclass__Метакласс во время создания класса сам подменяет
__slots__ и распластывает вложенные protobuf-сообщения в плоскую структуру:class FlatMeta(type):
def __new__(mcs, name, bases, namespace):
proto = namespace.get('_PROTO')
if proto:
slots = tuple(field.name for field in proto.DESCRIPTOR.fields)
def __init__(self, **kwargs):
for name, val in kwargs.items():
object.__setattr__(self, name, val)
namespace['__slots__'] = slots
namespace['__init__'] = __init__
return super().__new__(mcs, name, bases, namespace)
class UserDTO(metaclass=FlatMeta):
_PROTO = UserProto
Теперь UserDTO — плоский объект с
__slots__. Без лишних аллокаций при копировании.Почему это вывозит под high-flow
* Нет
__dict__ — объект занимает ровно размер полей плюс заголовок* Нет кэша валидации — все решается на этапе компиляции класса
* Можно пилить напрямую в
SerializeToString, без перегонки в словарьТипичная ошибка
Использовать здесь dataclass с декоратором — он все равно создает
__dict__ и добавляет лишний слой методов. Метакласс решает это на уровне создания класса.Практический совет
Для production: такой подход годится только когда поля статичны и не требуют runtime-атрибутов. Для сложной валидации Pydantic все равно нужен. Но для чистого DTO это просто жир.
Вывод:
__init_subclass__ с метаклассами — инструмент, который выжимает наносекунды там, где каждый чих на счету, но требует строгой дисциплины в проектировании контрактов.