вторник, 18 июля 2023 г.

[prog.c++] Мои собственные впечатления от работы над релизом SObjectizer-5.8.0

Состоялся релиз SObjectizer-5.8.0 и so5extra-1.6.0. Список изменений можно найти в Wiki проекта. На Хабре есть статья с более развернутым описанием некоторых из них. Здесь же я поплачусь про тяжелую жизнь поделюсь своими личными впечатлениями о работе над этим релизом, без формализма и официоза.

Все началось с message_sink-ов два года назад

По большому счету, ветка 5.8 -- это долгострой длиной почти в два года. ЕМНИП, началось все вот с этого вопроса в issues в апреле 2021-го. Вопрос о том, чтобы иметь простую и дешевую переадресацию сообщений из одного mbox-а в другой.

Вопрос был задан, но ответа на него у меня не было. Потребовалось больше полугода чтобы появилась первая смутная идея о том, как это вообще может быть внедрено в SObjectizer. А потом еще почти столько же, чтобы эта смутная идея начала приобретать более-менее четкие очертания.

Но даже когда в сентябре 2022-го я фиксировал примеры кода по использованию message_sink-ов, не было представления о том, как же воплощать это в жизнь. А вскоре после этого меня догнала какая-то странная простуда, которая вместе с другими факторами, привела к тому, что пришлось перейти на 4-х дневную рабочую неделю чтобы более-менее восстановиться. Так что к нормальной работе над SO-5.8 удалось приступить где-то в ноябре 2022-го. Чтобы в декабре опять выпасть на длительное время из-за очередной странной простуды.

Немного в сторону: формально диагноз COVID-19 мне ни разу не ставили, но есть подозрение, что с 2021-го по 2023 три или четыре раза я им переболел. К врачам не обращался, т.к. не было ни высокой температуры, ни проблем с дыханием. Основной симптом, который держался долго, до нескольких недель, -- это потеря работоспособности, когда сил хватало всего на 2-3 рабочих часа в день, а потом накатывала усталость и мозг просто отказывался о чем-то думать. И вот как раз два случая пришлось именно на разработку версии 5.8.

В общем, первые конкретные наметки по реализации message_sink-ов были сделаны в ноябре 2022-го, а задышало это все уже в феврале 2023-го.

Но потом возникла еще одна мысль: раз уж message_sink-и скрывают детали доставки сообщения до event_queue, то можно же переложить на message_sink-и и заботу о message_limits. Тем самым сильно упростив реализацию mbox-ов.

Мне это показалось очень важным, т.к. гибкость и удобство SObjectizer-а, думается, во многом определяется разнообразием mbox-ов и возможностью делать специализированные mbox-ы под специфические условия. А поддержка message_limits в реализации mbox-ов заметно усложняет написание собственных mbox-ов.

Но вот придумать как именно переложить работу с message_limits на message_sink-и удалось не сразу. Сильно не сразу.

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

Сейчас мне сложно судить о том, насколько хорошо получилось в итоге. На данный момент это лучшее, что удалось придумать. Наверняка все косяки проявятся со временем, тогда и будем посмотреть, как их исправить. В общем, прошу в пианиста не стрелять, играю как умею.

noexcept for evt_finish и желание двигаться в сторону работы без динамических аллокаций

С самого начала работ над собственно SObjectizer (тогда еще SObjectizer-4) было принято решение, что SObjectizer не будет инструментом для решения задач реального времени (не говоря уже про жесткое реальное время). Это было важно, поскольку предтеча, SCADA Objectizer, как раз таки позиционировался для задач реального времени.

Ну а поскольку SObjectizer для реального времени не предназначался, то динамическая память в SObjectizer активно применялась и применяется.

От использования динамической памяти в SObjectizer мы вряд ли когда-нибудь избавимся. И вряд ли когда-нибудь SObjectizer будет переориентирован на задачи реального времени (по крайней мере за наш счет). Но хочется дать пользователю возможность большего контроля за тем когда эта самая память выделяется.

В идеале хочется достичь того, чтобы пользователь мог преаллоцировать заранее все нужные ему вещи (диспетчеры с очередями, mbox-ы, агенты, сообщения и т.д.), а потом бы SObjectizer работал бы с этим всем вообще не обращаясь к new/delete.

Причем нужно это не только, да и не столько, для реального времени. В моем представление это необходимо и для "тяжелых" десктоп-приложений, падение которых из-за std::bad_alloc пользователя не порадует. Ну, действительно, делаете вы в каком-то CAD-е сложный чертеж, а в один прекрасный момент CAD падает без сохранения последних внесенных вами изменений. Чтобы такого не было, в программе нужно предусмотреть возможность безопасного и надежного отката к какому-то состоянию при возникновении исключений по типу std::bad_alloc. И если в приложении используется SObjectizer, то не хочется, чтобы именно SObjectizer приводил к std::terminate при выполнении такого отката.

В принципе, первые шаги к тому, чтобы пользователь мог пользоваться только преаллоцированными объектами в SObjectizer уже были сделаны. Так, уже давно поддерживаются преаллоцированные сообщения. Штатные диспетчеры, конечно же, используют хип для реализации своих очередей, но пользователь может написать собственный диспетчер.

Однако, оставались еще моменты связанные с использованием динамической памяти при дерегистрации агентов/коопераций. Как раз на устранение этих моментов было потрачено еще сколько-то времени в рамках релиза 5.8.0.

Отсюда же и появление гарантии "noexcept for evt_finish". Да, пока она обеспечивается только для двух новых диспетчеров. Но я не был готов к переделке старых штатных диспетчеров. И до сих пор не уверен, что такая переделка нужна. ИМХО, высоки шансы, что эта фича вообще не будет востребована и со временем ее придется выкинуть.

Так что я попробовал сделать еще один шажок в направлении того, чтобы SObjectizer-ом можно было пользоваться взяв работу с динамической памятью под строгий контроль. Остается посмотреть что из этого получится. Тем не менее, есть приятное теплое чувство внутри из-за того, что еще один кусочек технического долга был оплачен. Пусть и очень маленький.

Внезапное расширение Wiki проекта

Зафиксировали мы на GitHub-е версию 5.8.0 еще 30-го июня 2023-го. Тогда же отправили обновления для vcpkg/conan. Но даже спустя неделю новая версия SObjectizer (и so5extra) в vcpkg/conan принята не была.

Подобная задержка здорово била по нервам, ибо пока официального анонса релиза не было, я толком не мог заниматься другими делами, постоянно возвращаясь то к тексту статьи для Habr-а, то к тексту этого поста, то еще к чему-то связанному с релизом. Но эта задержка давала время на то, чтобы подготовить какие-то дополнительные материалы.

И, поскольку SO-5.8.0 в vcpkg/conan все никак не принимали и не принимали, то появилось время вернуться к вопросу, который подвис в воздухе еще четыре года назад, во время релиза версии 5.6.

Дело в том, что в ветке 5.6 мы пошли на серьезный слом совместимости с веткой 5.5. И это коснулось не только исходных кодов, но и документации, которая у нас к тому времени была накоплена в Wiki проекта на SourceForge.

Самую важную ее часть, а именно серию InDepth, рассказывающую про разные аспекты SObjectizer-а, я тогда переделал (в процессе переноса с SourceForge на GitHub). Но вот серию ByExample, которая знакомила новичка с SObjectizer на примерах, начиная от простого ко все более сложным, так и осталась на SourceForge для версии 5.5. Ниасилил тогда, а потом руки не доходили (в течении четырех лет, да).

А вот сейчас дошли. Так что зайдя в раздел SO-5.8 Documentation в Wiki проекта на GitHub-е теперь можно найти большую часть из той серии. Три или четыре раздела пришлось выбросить, т.к. там использовалось синхронное взаимодействие между агентами, которое сейчас в измененном виде живет в so5extra. Но подавляющая часть была перенесена и адаптирована под SO-5.8. Аллилуйя!

Что меня особенно порадовало, так это то, как мало пришлось менять в примерах кода и в описаниях, хотя версия 5.5 уже весьма старая и при переходе на 5.8 многое изменилось. Что подчеркивает, что основные принципы работы SObjectizer-5 на протяжении многих лет не меняются. И это очень сильно греет душу. Способствует возникновению теплого чувства внутри ;)

Почему работа над SO-5.8.0 длилась так долго?

Потому, что мы делаем свои OpenSource продукты за свой счет. И этот счет как-то нужно пополнять. Поэтому времени на тот же SObjectizer остается не так уж и много: всего пара-тройка часов в день.

Плюс к тому, конкретно при работе над версией 5.8.0 было несколько моментов, когда идею нужно было выносить и родить. На что также требуется время. Причем заранее непонятно сколько именно.

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

Будущее SObjectizer-а в современных условиях

В 2021-ом и 2022-ом годах мы дважды оказывались в ситуации, когда наши OpenSource проекты могли прекратить свое развитие. Пока пронесло (хотя у RESTinio застой вынужденно продолжается), но может быть это просто пока.

Посему скажу просто: я все еще вижу смысл в дальнейшем развитии SObjectizer-а. И, пока у меня есть возможность/потребность/желание, буду продолжать заниматься этим проектом. Возможности же, во многом, зависят от этого.


Xочу поблагодарить всех, кто обратил свое внимание на SObjectizer, задает нам вопросы, пробует его использовать, делится ссылками на него. И отдельная благодарность всем, кто помогал с очередным релизом.

PS. В этот раз я ограничусь анонсами в своих соцсетях (блог, LinkedIn, VK, twitter) и на паре русскоязычных профильных ресурсов (это LOR и RSDN, просто по старой памяти, ради традиции). На большее уже нет ни сил, ни нервов. Если кто-то сочтет возможным взять на себя труд запостить новость куда-то вроде Reddit или HackerNews, то хорошо. Если нет, то тоже хорошо, меньше обсуждений придется отслеживать. А то я, честно говоря, уже подзадолбался... 🙁

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