суббота, 13 января 2018 г.

[prog.c++] Тема с упрощением "асинхронных операций" в SObjectizer начинает дышать...

Данный пост продолжает тему, затронутую в двух декабрьских постах "Попытка упростить работу с отложенными сообщениями в SO-5" и "Еще одна попытка упростить работу с отложенными сообщениями в SO-5". В результате длительного и напряженного выкуривания бамбука удалось придумать, как же это все должно выглядеть. И уже начала дышать одна из реализаций. Кому интересно, милости прошу под кат. Для тех же, кто не интересуется SObjectizer-ом и C++ными наворотами, ничего интересного в данном посте не будет. Извините.

среда, 10 января 2018 г.

[prog.c++] Мой доклад приняли на C++Russia 2018

Собственно, вот: "Акторы на C++: стоило ли оно того?" Только акторы в докладе будут присутствовать постольку-поскольку, просто как некий фон, демонстрирующий особенности "предметной области". В основном же речь будет идти о C++. О том, насколько C++ помогал в разработке, где и когда мешал. Как менялся C++ и как это сказывалось. И как сказывалось то, что где-то C++ не менялся. Как изменилось отношение к C++ за прошедшие 15 лет и как это повлияло на нашу работу.

В общем, это будет доклад не про SObjectizer, а про то, что "С++, конечно, та еще субстанция, но конфетку-то сделать можно" ;)

понедельник, 8 января 2018 г.

[prog] Не Boost-ом единым...

Разведка донесла, что в slack-канале Boost-а проскочила ссылка на RESTinio-0.4. В ответ на что Винни Фалько, автор Boost.Beast, запостил ссылку на этот issue с предложением задействовать Boost.Beast в реализации RESTinio. И добавил к этой ссылке фразу: "The old "boost bad" canard."

Хочется сказать, что Винни не прав. В том, что мы не стали делать RESTinio на базе Boost.Beast, нет никакого подтекста из категории "Boost -- говно". Попробую объяснить, почему мы не хотим добавлять Boost.Beast в зависимости к RESTinio. Хотя такая идея нами обсуждалась где-то в мае или июне 2017-го, когда стало известно о сроках проведения review для включения Beast-а в Boost.

Первая причина в том, что С++разработчики, как уж сложилось, делятся на тех, кто использует Boost, и на тех, кто Boost не использует. Нам сейчас не важно, по каким причинам кто-то не использует Boost. Важно, что такой факт имеет место быть. И что разработчиков, которые не используют Boost, не так уж и мало. Пусть даже таких, грубо говоря, всего 10%, но это все равно не 0%. Следовательно, если мы сделаем RESTinio на базе Boost.Beast, то эти разработчики просто не будут рассматривать RESTinio. Для нас эти разработчики, как потенциальные пользователи, будут потеряны. Тогда как если RESTinio не будет иметь Boost в зависимостях, то RESTinio смогут использовать и те, кто применяет Boost, и те, кто держится от Boost-а подальше.

Такова се-ля-ви. Если мы заложимся на Boost, то мы отрежем часть потенциальных пользователей. Нам это не нужно. Как бы представители секты "Boost -- это наше все" не выдрачивали на свой любимый фреймворк, вне Boost-а тоже есть жизнь. И нам она так же интересна. Тем более, что представители секты "Boost -- это наше все" крайне не любят смотреть на то, что в Boost не входит. Вот есть в Boost-е Beast, значит встраиваемый HTTP-сервер нужно делать именно на Beast. И похер на то, что это займет больше времени и кода, зато Boost и вот это вот все. Так что даже с точки зрения банального маркетинга в большой аудитории пользователей Boost-а процент тех, кто не удовлетворится Beast-ом и пойдет искать что-то еще, очень невелик. Посему ценность этой аудитории будет не выше, чем ценность аудитории тех, кто Boost не использует. Значит, нам тем более нет смысла терять аудиторию тех, кто не использует Boost.

Вторая причина в том, что Beast берет на себя слишком много. Закладываясь на Beast мы лишаем себя значительной части контроля над тем, что происходит с вводом-выводом и парсингом HTTP-протокола. Тогда как http-parser из nodejs (как и picohttpparser) в этом смысле гораздо менее требовательные. Это позволяет нам, например, встраивать контроль за тайм-аутами операций. И еще, к примеру, у нас остается возможность дать разработчикам выбор между HTTP-парсерами: сейчас поддерживается только nodejs-овский http-parser, но если будут пожелания от пользователей, то мы можем добавить альтернативы. Тот же picohttpparser. Или даже какой-то кастомный, заточенный под одну конкретную задачу.

Т.е. контролируя почти все, что связано с вводом выводом и обработкой прочитанных/записываемых блоков данных, мы имеем большую гибкость. А так же свободу развернуть RESTinio в нужном нам и нашим пользователям направлении. Тогда как с Boost.Beast мы такой гибкости не видим.

Подчеркну еще раз. Мы уже обсуждали тему перевода RESTinio на базу Beast-а. И коллективно решили, что это не в наших интересах. У разработчика Boost.Beast своя задача. У нас своя.

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

Тогда как у разработчика Boost.Beast, на мой взгляд, цели совсем другие. Beast представляет из себя низкоуровневый конструктор, из которого, при желании, приложив достаточно сил и времени, можно собрать что угодно. Для каких угодно целей. Но, повторюсь, приложив достаточно времени и сил.

Можно ли в RESTinio совместить то, что хотим мы, с тем, что закладывалось в сам Beast? Может быть и можно. Хотя, как нам представляется, не просто. И, если бы мы начинали делать RESTinio сейчас, после релиза Boost-1.66, вопрос реализации RESTinio на базе Beast-а можно было бы рассматривать более внимательно. Но начали мы делать RESTinio сильно раньше. И переходить на Beast сейчас, с учетом всего вышесказанного, вряд ли разумно.


Если кто-то думает, что мы из тех, кто принципиально не использует Boost, то это зря. Случается, что и используем. Следы этого на публике можно обнаружить, например, в прототипе интеграции SObjectizer-а и libmosquitto. Но когда речь заходит о библиотеке, предназначенной для широкого использования, то вопрос помещения Boost-а в список зависимостей перестает быть праздным.

пятница, 29 декабря 2017 г.

[work-n-life] Послесловие к уходящему году...

В крайний рабочий день уходящего года можно попробовать сказать пару слов об итогах 2017-го в профессиональном плане. Да и не только в профессиональном.

2017-й оказался первым полным годом для нашей небольшой компании "СтифСтрим". В этом году мы закрыли свой первый контракт. В том числе и выполнили свои гарантийные обязательства по нему. Немного продвинули вперед SObjectizer. Больших релизов было всего два - версии 5.5.19 и 5.5.20, но зато было еще и несколько промежуточных, корректирующих релизов. SObjectizer получил поддержку vcpkg (спасибо Anton Stuk) и попал в ALT Linux (спасибо Pavel Vainerman).

Сделали пять больших докладов на различных конференциях. В том числе попали и на крупнейшую конференцию по C++ в СНГ -- C++Russia. Опыт очень интересный и полезный. Опубликовали одиннадцать статьей на Хабре.

Запустили два новых продукта: so_5_extra и RESTinio. Оба проекта стартовали с двойным лицензированием и прицелом на продажу лицензий. Но в отношении RESTinio наши намерения не нашли понимания у публики, поэтому мы перевели RESTinio под BSD-3-CLAUSE. Релизы RESTinio под пермиссивной лицензией были приняты очень благосклонно, в частности анонсы на reddit-е вызвали большой интерес. Так же RESTinio довольно неплохо показал себя в Mail.ru-шном HighloadCup-е.

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

Еще одна область, в которой ярчайшим образом проявилось отсутствие какого-либо опыта -- это маркетинг. Мы только начали учиться продвигать себя. Заработок на OpenSource-продуктах -- дело непростое и не быстрое, для поддержания штанов нужно брать заказы. Для этого нужен маркетинг самих себя, чему мы еще только-только учимся. Учиться трудно, т.к. область деятельности у нас специфическая, а популярная литература на этот счет, такое ощущение, ориентируется на обучение маркетингу товаров массового спроса. В общем, если кому-то нужно сделать что-то сложное на C++ или же нужно починить что-то сложное на C++, то вы знаете, к кому обращаться ;)

Резюмируя: год оказался не простой (не смотря на уверения математиков), ну и результат получился фифти-фифти, где-то плюс, где-то минус. Похоже, следующий год будет сложнее. Но и мы уже опытнее, так что это нас не пугает.


В завершение хочу сказать спасибо всем читателям блога. В этом году в блог я писал меньше. Интересных материалов, наверное, так же оказалось меньше. Может быть даже сильно меньше. Но спасибо, что продолжаете меня читать. Это и радует и, местами, вдохновляет. Плюс огромное количество полезной информации и соображений в комментариях. Так что еще раз спасибо. Да! Еще в 2017-ом удалось развиртуализироваться и пообщаться в живую с несколькими давними виртуальными знакомыми. Это было круто.

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

С НАСТУПАЮЩИМ И ВСЕГО САМОГО ХОРОШЕГО В 2018-ом!

понедельник, 18 декабря 2017 г.

[prog.flame] Тут вот Boost-1.66 подтянулся с Beast-ом...

...и уже пошли восторженные отзывы о том, как же круто иметь поддержку HTTP в Boost-е и как же народу хочется поиграться с Beast-ом.

Ну что сказать? Посмотрим, как много из тех, кто попробует, всерьез возжелает работать с таким низкоуровневым кодом. Ну, чтобы было понятно, вот штатный пример асинхронного сервера на Beast-е. Страшно не стало? Ну тогда попробуйте туда добавить, скажем, контроль тайм-аутов для соединений. Все еще не страшно? ;)

А ведь многие попробовавшие, наверняка, будут довольны. И будут пользоваться таким низкоуровневым API. Ибо копипаста рулит и бибикает.

ЗЫ. Этот пост вовсе не наезд на библиотеку Beast. Сама-то она очень круто сделано. Но надо понимать, что Beast -- это конструктор, который позволяет вам собрать все, что вы захотите. Только вот собирать вам все придется самостоятельно и из очень мелких кусочков. Посему не очень правильно рассматривать Beast как готовый инструмент для конечных прикладных разработчиков. Это набор базовых строительных блоков. Хороший набор. Но только набор. Так что это скорее наезд на восторженных неофитов, которые ждут какого-то чуда уровня Go-шного fasthttp. Чуда не будет ;)

[prog.c++] Еще одна попытка упростить работу с отложенными сообщениями в SO-5

Прошу прощения у тех читателей блога, которым не интересно читать посты про SObjectizer. Но данный пост будет продолжением темы про отмену отложенных сообщений, начатую на прошлой неделе. Тогдашнее обсуждение показало, что предлагаемый способ вряд ли можно считать хорошим, к тому же он не решал определенных потребностей отдельных пользователей SO-5. Поэтому данная тема продолжила занимать мое внимание и вот очередная итерация. Кому интересно понаблюдать за эволюцией решений, которые со временем [не]попадают в SObjectizer, милости прошу под кат. Для всех остальных там ничего интересного не будет, сорри. Блог так устроен, что я пишу сюда о том, что занимает меня в конкретный момент времени...

четверг, 14 декабря 2017 г.

[prog.c++] Попытка упростить работу с отложенными сообщениями в SO-5

Удобная и простая работа с таймерами -- это одна из важных причин использования акторов вообще и SObjectizer-а в частности. Вот, скажем, в примере для вчерашней статьи на Хабре, мне потребовалось сгенерировать цепочку событий, происходящих спустя определенное время. Что элементарно выполняется посредством простого использования функции send_delayed:

std::vector<milliseconds> delays{ 125ms, 250ms, 400ms, 500ms, 700ms, 750ms, 800ms };

for(const auto d : delays) {
   const std::string msg = std::to_string(d.count()) + "ms";
   so_5::send_delayed<std::string>(env, ordinary_mbox, d, msg);
   so_5::send_delayed<std::string>(env, anti_jitter_mbox, d, msg);
}

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

Однако, при работе с отложенными сообщениями в SObjectizer-5 есть очень важный нюанс: не так-то просто отказаться от отосланного отложенного сообщения. Допустим, вы начали операцию, взвели отложенное сообщение, а результат операции пришел раньше. Вроде как отложенное сообщение вам больше не нужно. И тут вы можете оказаться в одной из двух ситуаций: