среда, 27 марта 2024 г.

[prog.thoughts] "Универсальный" против "специализированного" на примере из SObjectizer-а

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

В SObjectizer агенты подписываются на сообщения: если подписка есть, то сообщение до агента может дойти, а если подписки нет, то сообщение точно не дойдет. А раз есть подписки, то их нужно как-то хранить. Соответственно, возникает простой вопрос: "Как хранить?"

Фокус в том, что заранее неизвестно, сколько у агента будет подписок. Может быть две, может быть двадцать две, может быть две тысячи и двадцать две. А может и двести тысяч. Ну мало ли. Никто же не запрещает 😉

Как по мне, так это означает, что невыгодно в агенте хранить подписки одним и тем же способом вне зависимости от количества этих самых подписок. Ведь нет контейнеров, которые бы отлично работали бы при любом количестве элементов. Так, если у нас всего две подписки, то hash-таблица избыточна, как и бинарное дерево поиска (где каждый узел -- это отдельный объект в динамической памяти). А если у нас 100500 подписок, да они еще и активно создаются/уничтожаются, то непрерывный вектор здесь не вариант, т.к. вставки в середину (как и удаления из середины) дороги.

А раз так, значит напрашивается введение отдельного понятия, subscription_storage. Т.е. некого интерфейса, который будет скрывать детали хранения подписок. Соответственно, в агенте хранится ссылка на subscription_storage, а вся работа с подписками ведется через интерфейс subscription_storage.

Появление же этого интерфейса не может не сказаться на производительности. Ведь у нас появляется дополнительная косвенность. Плюс у самих реализаций subscription_storage могут быть какие-то дополнительные накладные расходы...

Вот и получается, что не зная конкретных сценариев использования приходится делать универсальное решение, которое, в лучшем случае, можно настроить под определенные условия.

Тогда как делая специализированный фреймворк под задачу те же самые подписки можно хранить максимально эффективным для задачи способом. Непосредственно в агенте, без какой-либо промежуточной косвенности в виде абстрактного интерфейса subscription_storage. Что и даст пусть небольшой, но выигрыш.

А сумма таких небольших выигрышей по разным категориям и приведет к тому, что специализированное решение практически всегда будет эффективнее, чем универсальный фреймворк.

Мораль сей басни: универсальные фреймворки не столько про эффективность результирующего года, сколько про уменьшение геморроя при разработке. И про значительное снижение требований к квалификации тех, кто будет посредством фреймворка решать прикладную задачу.

ЗЫ. У SObjectizer-а давеча состоялся очередной релиз. Как раз была добавлена еще одна реализация subscription_storage. И таки дошли руки сделать описание этой штуки в Wiki-проекта.

Комментариев нет: