вторник, 5 ноября 2024 г.

[prog.c++] Послесловие к релизу SO-5.8.3: будет ли SO-5.9 и если будет, то когда?

Осенью 2014-го года мы выпустили первую версию в ветке 5.5. Эта ветка затем развивалась пять лет без серьезных ломающих изменений. Я бы был не против и дальше обходится без заметных переделок, но, к сожалению, версия 5.5 набрала такой груз разнообразных фич, который стало уже тяжело нести. Накопился опыт, взгляды на какие-то вещи принципиально поменялись и было решено разгрести накопившийся наслоения не всегда хорошо сочетающейся функциональности. Так в 2019-ом появилась ветка 5.6.

Cчитаю, что в течении последних пяти лет именно эта ветка и развивается. Хотя, формально, мы сделали переход от 5.6 к 5.7, а затем и к 5.8, поскольку были пусть и небольшие, но ломающие совместимость изменения. Тем не менее, различия между 5.6 и 5.8 гораздо меньше, чем между 5.5 и 5.6. Так что для меня лично 5.6/5.7/5.8 -- это развитие одной и той же линии романа и изменение номера версии всего лишь дань формализму.

Сейчас заканчивается 2024-й год и получается, что семейство 5.6/5.7/5.8 поступательно развивается уже пять лет. Вроде бы повторяется история с пятилетним циклом жизни 5.5 и пора задумываться о том, что дальше.

На данный момент, в отличии от ситуации с 5.5, я не вижу каких-то фатальных недостатков в семействе 5.6/5.7/5.8. Необходимости разгрести авгиевы конюшни пока нет. ИМХО, у 5.8 еще есть запас прочности для продолжения в том же духе.

Поэтому какой-то насущной необходимости начинать ветку 5.9 нет.

Насущной нет, но есть вопрос с освоением новых стандартов C++. И в 2025-ом нужно будет всерьез задумываться над этим вопросом.

Пока что хватает и C++17. И для библиотеки хорошо, когда она отстает от самого-самого свежего стандарта -- тем самым больше проектов могут ее использовать. Но в какой-то момент возникает вопрос: а стоит ли это "хорошо для сторонних проектов" того, что мы отказываемся от плюшек современного C++?

В 2019-ом было решено, что невыгодно дальше держаться за C++11.

Полагаю, в ближайшие полтора-два года так же невыгодно станет держаться и за C++17. Вот тогда на горизонте и появится ветка 5.9.

Это один возможный сценарий развития событий.

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

Ведь сейчас в SObjectizer аллокации/деаллокации буквально на каждом шагу: за send-ом скрывается new, постановка заявки в очередь к агенту может вести к аллокациям, подписка или установка delivery filter требует аллокаций, даже смена состояния агента, если для состояния используется time_limit, требует аллокаций.

Подобное поведение автоматически ставит крест на применении SObjectizer в системах реального времени. Что иронично, т.к. SObjectizer вырос из SCADA Objectizer, создававшегося именно под реальное время. Но в этом я не вижу ничего страшного, ну нет и нет.

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

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

Прекрасно понимаю почему так, да и сам далеко не всегда готов платить за разработку дороже, если крах при bad_alloc-е вполне себе допустим.

Но что делать когда крах при bad_alloc-е ну такое себе? Вот тот же прокси-сервер с 200k одновременных подключений... Он рестартует, это OK. Вполне вероятно, что он рестартует за считанные секунды, а то и быстрее. Тогда как восстановление этих 200k соединений -- это же не быстрый процесс. Это неизбежно скажется на впечатлении пользователей от качества сервиса. Но, что хуже, у нас нет устойчивости против подобных падений в будущем. Допустим, мы принимаем 200k подключений и работаем нормально, но затем приходит одно специфическое подключение, при работе с которым мы вынуждены активно потреблять память и это ведет нас напрямую к очередному bad_alloc-у. И мы опять падаем роняя 200k соединений. А через какое-то время все повторяется вновь.

Если же поставить себе целью написать код, который может пережить bad_alloc, то придется придумать какую-то стратегию выживания. У нас должен быть набор действий по восстановлению (например, закрытие проблемного соединения и очистка связанных с ним ресурсов). И, что важно, мы должны быть уверены, что при выполнении данного набора действий у нас нет никаких динамических аллокаций (ведь каждая новая аллокация в таких условиях может вести к повторному bad_alloc-у).

Достигаться это может либо за счет того, что в этом наборе действий мы задействуем только заранее преаллоцированные объекты, либо же какой-то специальный аллокатор, который работает с заранее зарезервированным блоком памяти.

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

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

Вот под добавление в SObjectizer чего-то подобного я бы начал ветку 5.9 не раздумывая прям завтра (но не сегодня, сегодня уже поздновато). Но...

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