вторник, 27 июля 2021 г.

[prog.c++] Первые впечатления от C++ных короутин и зачем мне все это нужно?

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

В C++20 нет короутин

Понимаю, что на этот счет есть разные мнения, но лично мне после знакомства с тем, что включили в C++20, проще считать, что в C++20 короутин нет.

Есть механизм поддержки короутин со стороны языка.

А вот самих короутин нет.

ИМХО, это большая разница.

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

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

Изучение механизма поддержки короутин в C++20 -- это та еще головоломка

Мягко говоря, это просто какой-то трындец.

Я вкуриваю эти самые короутины уже пять дней. И все еще никак.

Не, поятно, что я не показатель, т.к. старый и впавший в маразм старпёр. Но, судя по отзывам, проблемы с изучением есть не только у меня. Что пугает.

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

Проблема в моем случае в том, что моих мозгов на осознание всей гениальности замысла не хватает. Что расстраивает.

По большому счету детали механизма поддержки короутин в C++20 мало кому будут нужны

Расчет комитета по стандартизации C++ был в том, чтобы добавить в язык сам механизм. Чтобы те или иные реализации подтянулись со временем.

Как я понимаю, в Asio-1.19 эта реализация уже есть.

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

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

Смущает, правда, наличие "закона текущих абстракций", согласно которому понимание того, что же происходит "под капотом" все же желательно. Но насколько все это будет актуально покажет только время. Будем посмотреть.

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

Зачем мне это все?

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

Во-вторых, если наши SObjectizer и RESTinio продолжат свое развитие, то нужно понимать, где и как короутины могут пригодится. И уже сейчас кажется, что пригодиться могут.

Короутины в SObjectizer

Пока не видно, чтобы короутины нужны были где-то в потрохах SObjectizer-а.

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

Сейчас если агент A хочет синхронно обратиться к агенту B (т.е. в обработчике событий E отослать сообщение агенту B и тут же, прямо внутри E дождаться ответа), то программист должен гарантировать что A и B работают на разных контекстах.

Тогда как в случае с короутинами можно сделать так, чтобы обработчик событий E сам был короутиной. Вызов операции ожидания ответа от B реализовывался бы через co_await. Например, что-то вроде:

so_5::awaitable_t A::evt_E(mhood_t<some_msg>) {
  // Создаем message chain для ответного сообщения.
  so_5::mchain_t reply_chain = so_5::create_mchain(so_environment());
  // Отсылаем сообщение агенту B и передаем в нем reply_chain, чтобы
  // агент B знал, куда отсылать ответ.
  so_5::send<some_request>(B_mbox, ..., reply_chain, ...);
  ...
  // Здесь мы хотим получить ответ.
  co_await so_5::receive(from(reply_chain).handle_n(1), ...);
}

Фокус здесь в том, что диспетчер, на котором запускается A::evt_E сможет понять, что здесь у нас короутина. И когда она приостановится на вызове co_await, то можно перейти к обслуживанию следующей заявки.

А это позволяет запросто привязать агентов A и B к общему рабочему контексту. При этом они смогут "синхронно" общаться друг с другом.

Что очень круто, т.к. раньше такое в принципе было невозможно.

Короутины в RESTinio

А вот в RESTinio для применения короутин открывается гораздо больший простор. ИМХО.

Короутины в реализации самого RESTinio

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

Короутины в реализации request_handler-ов

Очевидное применение короутин для упрощения жизни пользователям RESTinio -- это представление request_handler-ов в виде короутин.

Сейчас, если пользователь хочет сделать именно асинхронную обработку входящих запросов, то он должен в request_handler-е делегировать куда-то саму обработку и вернуть управление назад RESTinio.

В случае же, если request_handler будет представлен в виде короутины, то внутри request_handler-а можно инициировать асинхронные операции посредством co_await. Что, потенциально, сделает написание асинхронных обработчиков входящих запросов гораздо более простым занятием.

Поддержка исходящих соединений в RESTinio?

На данный момент RESTinio позволяет работать только с входящими HTTP-запросами, а исходящие запросы не поддерживаются в принципе. Т.е. RESTinio не может сейчас использоваться в качестве HTTP-клиента.

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

А вот применение короутин, потенциально, может этот момент прояснить. Например, что-то вроде:

auto reply = co_await client.http_post(restinio::async, "https://google.com", ...);

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

Я не хочу сказать, что наличие короутин делает добавление поддержки исходящих HTTP-запросов в RESTinio простым и понятным делом. Но внушает надежду, что такая поддержка может быть сделана красиво и удобно для пользователя.

Вместо заключения

В ближайший день-два я попробую написать пост, в котором расскажу, что именно затрудняет для меня разбирательство с механизмом короутин в C++20. Это нужно лично мне, т.к. надеюсь, что в процессе написания текста информация в мозгах структурируется чуть лучше. Но может кому-то это так же будет интересно.


Возможно, кто-то использует RESTinio в своих проектах и планирует со временем переходить на C++20. Если так, то вы можете быть заинтересованы в том, чтобы в RESTinio появилась поддержка короутин. Ускорить этот процесс можно за счет финансирования наших работ по RESTinio. Например, в виде договора между вашей компанией и СтифСтримом.

Тоже самое касается и SObjectizer-а.

вторник, 20 июля 2021 г.

[prog.thoughts] Мое текущее отношение к поддержке исключений в C++

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

Попробую рассказать о том, как я сам сейчас отношусь к существующей в C++ поддержке исключений.

Ключевое

Хорошо, что исключения в C++ есть. Как уже говорилось в предыдущем посте, лично я плохо себе представляю как писать надежный код без использования исключений при программировании в стиле "современного C++".

Плохо то, что текущая реализация исключений:

понедельник, 19 июля 2021 г.

[prog.experience] Несколько слов о работе с исключениями в arataga

Сегодня попробую выполнить обещание, данное в предыдущем посте, и попытаюсь рассказать немного о том, к чему на данный момент пришла работа с исключениями в arataga (если кто-то не в курсе, то arataga -- это прототип производительного прокси-сервера, который мы делали для одного клиента, пока этот самый клиент не потерял интерес к данной разработке).

Особенности arataga и их влияние на работу с исключениями

Во-первых, изначально проект arataga разрабатывался в сжатые сроки и требовалось как можно быстрее получить работающий прототип чтобы оценить перспективность всей затеи. Т.е. ключевым фактором являлся "time to market". Писать на C++ в условиях горящих сроков -- то еще занятие. Поэтому для нас важно было использовать практики, которые бы обеспечивали нам и достаточно высокую скорость разработки кода, и достаточную степень его надежности и корректности.

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

В-третьих, архитектура arataga подразумевала, что будет всего один процесс, который будет обслуживать все подключения. Откуда следует то, что принцип fail-fast в смысле "если возникла непредвиденная неприятность, то просто грохаем весь процесс" здесь был бы не очень уместен. Подключений десятки тысяч, с каким-то из них точно что-то пойдет не так. Ронять все приложение вместе со всеми остальными подключениями не есть хорошо. Как следствие, нам пришлось разбираться с тем, чтобы неожиданные исключения, с которыми мы не знаем что делать, не всегда вели к краху всего приложения, а в каких-то местах просто игнорировались бы.

В-четвертых, хотя arataga и должен был работать в режиме 24/7, но жестких требований к тому, чтобы arataga не падал в любых условиях, у нас не было. Эпизодические падения в непредвиденных ситуациях, скажем, раз в неделю, никого бы не напрягали. Поэтому мы могли не заморачиваться на тотальный контроль исключений и в каких-то местах могли позволить себе смотреть на ситуацию так: "ну, если уж здесь что-то вылетит, то пусть уж лучше все просто навернется и рестартует".

В-пятых, в arataga активно используются сторонние библиотеки, которые либо не очень приветствуют выброс исключений в callback-ах (как Asio, например), либо же вообще этого не приемлют (как, например, чисто C-шная http-parser, которая про C++ные исключения ни сном, ни духом). Но callback-и в эти сторонние библиотеки передаются C++ные, в которых активно используется C++ный код, бросающий исключения. И это нужно было как-то брать под контроль.

пятница, 2 июля 2021 г.

[prog.experience] Маленькая история про улучшение навигации по логам в arataga

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

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

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

Поскольку нагрузка создавалась не тестовыми программами, а реальными клиентами, трафик которых был пущен через arataga, то мы столкнулись с рядом особенностей в реализации SOCKS/HTTP-протоколов. И для разбирательства с тем, правильно ли arataga ведет себя в тех или иных ситуациях, потребовалось шерстить логи.

Грубо говоря, ищешь в логе ситуацию, помеченную как WARN или ERR, а затем смотришь, что предшествовало и/или следовало за этой ситуацией.

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

Изначально казалось, что каждая строка лога содержит достаточное количество информации для идентификации конкретного подключения. Вот, например:

[2021-04-16 08:43:02.756] [arataga] [error] socks-3001-192.168.1.178-io_thr_1-v1: connection (3001,38) => socks5: PDU with auth methods too long, methods: 1, bytes read: 22
[2021-04-16 08:43:02.756] [arataga] [debug] socks-3001-192.168.1.178-io_thr_1-v1: connection (3001,38) removed (protocol_error), connections: 0/200

Здесь в каждой строке есть две метки, которые позволяют идентифицировать точку входа и конкретное соединение в этой точке входа:

  • socks-3001-192.168.1.178-io_thr_1-v1 -- это имя агента, который обслуживает конкретную точку входа. Имя составное и сообщает максимум информации об этой точке входа и об агенте: socks -- говорит о точке входа по протоколу SOCKS, точка входа открыта на порту 3001 адреса 192.168.1.178, точка входа привязана к io_thread с порядковым номером 1. Ну и это первая версия данного агента (если агент пересоздается в результате изменения конфигурации, то номер его версии будет увеличиваться);
  • (3001,38) -- это идентификатор соединения внутри конкретной точки входа (38-ое соединение на порту 3001).

По идее, если искать подстроки "socks-3001-192.168.1.178-io_thr_1-v1" и "(3001,38)", то в логе будет найдено все, что касается данного конкретного подключения на данной конкретной точке входа.

Проблема, однако, в том, что искать по двум подстрокам не удобно. Гораздо удобнее искать всего одну подстроку. А именно "(3001,38)" вместо "socks-3001-192.168.1.178-io_thr_1-v1".

Это проблема проявилась практически сразу, еще когда мы сами занимались отладкой первых версий arataga на собственных тестовых стендах. Собственно, поэтому и появилась в логе отдельная связка из номера порта и номера соединения на этом порту (та самая подстрока вида "(3001,38)"). Это помогало нам в нашей автономной отладке, т.к. у нас не было повторений номеров портов на точках входа.

Но когда arataga поработала под реальной нагрузкой в условиях, когда есть сотни точек входа с одинаковым номером TCP-порта (на разных IP-адресах), то выяснилось, что подстроки вида "(3001,38)" уже не позволяют легко отыскивать все, что касается конкретного подключения. Слишком уж много оказывалось вхождений "(3001,38)", относящихся к совсем другим точкам входа.

Поэтому arataga была немного доработана дла того, чтобы от пары (порт, номер соединения) перейти к триплету (уникальный ID, порт, номер соединения), где "уникальный ID" был бы неким более коротким и удобным синонимом для "socks-3001-192.168.1.178-io_thr_1-v1".

В результате сейчас в arataga записи в логе имеют вид:

[2021-04-29 09:04:34.558] [arataga] [error] http-5500-192.168.1.161-io_thr_0-v1: connection (6498_2185,5500,6) => update request-target failure: unable to parse request-target, http_parser_parse_url result: 1

Где подстрока "(6498_2185,5500,6)" уже однозначно указывает на строчки лога, относящиеся к конкретному соединению на конкретной точке входа (уникальный ID вида "6498_2185" назначен агенту "http-5500-192.168.1.161-io_thr_0-v1" при его создании):

[2021-04-29 09:04:33.981] [arataga] [info] http-5500-192.168.1.161-io_thr_0-v1: created, acl_id_seed: 6498_2185


Пора переходить к итогу и к морали.

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

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

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


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

четверг, 1 июля 2021 г.

[life.cinema] Очередной кинообзор (2021/06)

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

Но, чтобы убить всякую интригу и не порождать напрасных ожиданий, скажу кратко: глянуть можно разве что "Кислород" и, если вам понравилась первая часть "Тихого места", то "Тихое место 2" (но лучше не ждать чего-то выдающегося). И все, сорян.

Фильмы

Кислород (Oxygène, 2021). Был приятно удивлен. Не ждал от продукции Netflix чего-нибудь толкового. Но у них получилось. Посмотрел с удовольствием.

Тихое место 2 (A Quiet Place Part II, 2021). Если вам понравился первый фильм, то можно посмотреть и второй. Ну а если первый восторга не вызывал, то и второй точно не вызовет. Как по мне, то вторая часть смотрится даже хуже, чем первая. Плюс у них серьезный косяк с приглашением на роль сына того же актера, что и в первой части (мальчик за 3 года сильно вырос и в продолжении это выглядит несуразно).

Бесконечность (Infinite, 2021). Красочно и местами даже динамично. Но блин, насколько же все тупо! Хотя, если этот фильм ориентирован на зрителей в возрасте 10 лет, то может и нормально для такой аудитории.

Дальний космос (Stowaway, 2021). Вот реально был неплохой заход на то, чтобы снять достойную космическую фантастику. Но, во-первых, получилось слишком нудно и затянуто. Во-вторых, почему-то в фильме не уделили никакого внимания тому, как "безбилетник" вообще попал на борт. В-третьих, почему-то сопереживать персонажам не хочется. Может быть потому, что в какие-то моменты они ведут себя как идиоты.

Первый клон (Seobok, 2021). По описанию и трейлеру ожидал, что будет бодрый фантастический боевик. Оказались фантастически нудные сопли. Смотреть можно разве что тем, кто интересуется корейским кино.

Ледяной драйв (The Ice Road, 2021). Халтура. Как по задумке, так и по исполнению.

Игры шпионов (The Courier, 2020). Не зашло. Смотреть было не интересно (особенно после прочтения вот такого взгляда на значимость предателя Олега Пеньковского). Такое ощущение, что основная цель съемок сего фильма была в том, чтобы дать Камбербэтчу повторить подвиг Кристиана Бейла в "Машинисте". Ну а появление в фильме гостиницы под названием "Отель Василий" просто подвело жирную черту под всем этим безобразием.

Сериалы

За час до рассвета (2021). Треш, угар и голые сиськи. Впрочем, при нынешней глобальной толерастии "голые сиськи" -- это еще неплохо, могла бы быть и содомия в худшем смысле этого слова. Всерьез это творение обсуждать невозможно, настолько там все убого, уныло и оторвано от реальности, что главный и единственный вопрос -- где же авторы брали такую траву?

Призрак (2019). Редкая дрянь. Смело можно не смотреть.

вторник, 8 июня 2021 г.

[prog.wtf] Ну вот правда, как с этим жить?

Честно, не представляю себе, как можно дальше жить в мире, где нормальным считается применение инструмента, провоцирующего на написание чего-то вроде:

add_executable(myapp main.cpp foo.c bar.cpp zot.cu)
target_compile_definitions(myapp
  PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:COMPILING_CXX_WITH_CLANG>
          $<$<COMPILE_LANG_AND_ID:CXX,Intel>:COMPILING_CXX_WITH_INTEL>
          $<$<COMPILE_LANG_AND_ID:C,Clang>:COMPILING_C_WITH_CLANG>
)

Если кто не в курсе (счастливчики!), то здесь условные операторы в угловых скобках. Вложенные.

И если бы не специальная поддержка в CMake магической COMPILE_LANG_AND_ID, то приведенный выше фрагмент пришлось бы записать вот так:

target_compile_definitions(myapp
  PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:AppleClang,Clang>>:COMPILING_CXX_WITH_CLANG>
          $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:Intel>>:COMPILING_CXX_WITH_INTEL>
          $<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:Clang>>:COMPILING_C_WITH_CLANG>
)

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

Однако, никогда у меня не бывает настолько же сильного желания уйти навсегда из С++, как в случаях, когда самому приходится погружаться в CMake-код. Да и не только из мира C++, но и вообще из программирования.

PS. Месяца четыре назад была возможность послать C++ к чертям собачим не нарушая никаких обязательств. Почему не воспользовался... Эх.

понедельник, 7 июня 2021 г.

[life.music] Продолжение саги о выборе хороших, но недорогих наушников на Aliexpress. Обзор побывавших у меня динамических вкладышей

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

Снимков наушников практически не будет, т.к. их слишком много и выглядят они в общем-то весьма однотипно. Приношу извинения, но возиться с фотографированием этого добра очень не хочется. Так что буду прилагать скриншоты со страничек этих наушников/динамиков на Aliexpress.

[prog.c++] Презентация о проекте arataga на английском

Подготовили презентацию о проекте arataga на английском языке. Надеюсь, кому-то будет полезна, поскольку не так-то и просто найти информацию о том, как же модель акторов применяется на практике в реальных C++ных проектах.

Эта же презентация есть на SlideShare.

суббота, 5 июня 2021 г.

[life.politics] Промежуточные впечатления от истории с посадкой рейса Ryanair и Романа Протасевича

Простите за политоту. Но поделюсь своим дилетантским мнением после просмотра того, что на ОНТ показали про рейс Ryanair и Романа Протасевича, а так же после прочтения нескольких заметок в Интернетах с разными точками зрения на происходящее.

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

Слили его вовсе не нашему КГБ. А, как мне думается, российским спецслужбам. И вся эта история с минированием борта Ryanair -- это не наши контрразведчики подсуетились, а российские.

Ибо, как мне думается, единственной стороной, которая при этом ничем не рискует, но получает большие дивиденды в случае успеха -- это Россия:

  • мало что так резко перекрывает возможности продолжения политики бахатовекторности и так настоятельно двигает в сторону реинтеграции с Россией, как новые санкции для РБ со стороны Европы;
  • белорусский КГБ обязательно поделится с российским ФСБ информацией от Протасевича касательно переориентирования части telegram-каналов на российскую повестку;
  • у России появляются дополнительные формы болевого воздействия на Украину. Типа угрозы передачи Протосевича в ЛНР (или приезда в Минск следователей из ЛНР). Или признанием Белоруссией Крыма российским.

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

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

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

Т.е. вся эта история с Протасевичем была чем-то выгодна лидерам протеста за границей (какой-то из группировок этих лидеров). И очень выгодна РФ. А вот кому практически не выгодна -- так это РБ.

В Интернетах были вопросы о том, почему же Протасевич не уничтожил данные на своих носителях перед задержанием. Даже если не брать в расчет тот факт, что надежно удалить данные не так-то и просто, если ты не знаешь, как именно это делать, то в условиях внезапной и незапланированной посадки можно тупо не успеть это сделать.

Но главная причина, как мне кажется, в том, что Протасевич осознал, что с информацией на носителях его ценность для нашего КГБ гораздо выше, чем без нее. А цена вопроса для него здесь высока как никогда. Так что, по моему мнению, он специально не стал уничтожать информацию на смартфоне и ноутбуке.

Вот такое впечатление сложилось на эту злободневную тему.

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

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

вторник, 1 июня 2021 г.

[life.cinema] Очередной кинообзор (2021/05)

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

Восемь сотен (Восемьсот, Ba bai, 2020). Отличное кино про войну. Местами просто шедеврально. Местами затянуто, пафосно и сопливо. Посмотреть однозначно стоит, но не слабонервным.

Гнев человеческий (Wrath of Man, 2021). Здорово, Ричи снял классное кино. Вот только когда Джейсон Стэйтем в главной роли, то особой интриги нет -- очевидно же, что с его героем ничего плохого случиться не может.

Избави нас от лукавого (Daman akeseo guhasoseo, 2020). Суровый корейский боевик. Только голову нужно отключить и смотреть просто как на динамичный (местами) аттракцион.

Заступник (The Marksman, 2020). Меня фильм приятно удивил. Думал, что Лиам Нисон снялся в очередном подобии "Заложницы" и опять будет круче всех крутых. Но нет, здесь все сняли с поправкой на его возраст. Так что за исключением финальной разборки все смотрится достаточно неплохо. Хотя и скучновато.

Армия мертвецов (Army of the Dead, 2021). Отличный аттракцион: перестаешь думать и наслаждаешься бодреньким экшеном на экране. Любителям фильмов про зомби смотреть обязательно. Меня, правда, несколько раздражало стремление снимать на открытой диафрагме с малой глубиной резкости, но это уже придирки.

Афера по-итальянски (Gli uomini d'oro, 2019). Мне зашло. Но фильм своеобразный, так что рекомендовать к просмотру не возьмусь. С большой вероятностью это фильм на любителя.

Асоциальная сеть (Silk Road, 2020). Неплохо. Но, как мне показалось, держалось все на игре всего лишь одного актера.

Попадос (Pixie, 2020). Так и не понял, что это было. Какой-то закос под Гая Ричи и Квентина Тарантино. Но явно неудачный. Можно и не смотреть.

Без жалости (Without Remorse, 2021). Редкого дебилизма фильм. Смотрел специально чтобы проверить так ли это. Так. Посему лучше вообще не тратить свое время на такое Г.


Теперь о фильмах, которые досмотреть не удалось.

Майор Гром: Чумной Доктор (2021). Как по мне, так отличная демонстрация того, что для американца хорошо, то для русского смерть. Ну не ложится стилистика американских комиксов на наш менталитет. Особенно когда нашу повседневную реальность начинают подгонять под то, что привычно американскому зрителю (поэтому типа полицейский участок не вызывает ничего, кроме гомерического хохота). В общем, меня хватило минут на 20.

Те, кто желает мне смерти (Those Who Wish Me Dead, 2021). Тупость происходящего на экране начинает убивать с самого начала, а затем градус идиотии только растет. Я держался, держался, но на моменте коротких перебежек по минному полю под минометным обстрелом грозовыми ударами сил терпеть больше не осталось.

понедельник, 31 мая 2021 г.

[work] У stiffstream есть пара свободных рук. Моих свободных рук

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

В последние 7 лет занимался развитием таких открытых проектов, как SObjectizer/so5extra, RESTinio, json_dto. Что включало в себя выбор функциональности для нового релиза, проектирование, реализация, тестирование, документирование, реагирование на issues и какой-никакой PR (более 50 статей на Хабре с 2016-го года + выступления на конференциях CoreHard C++ и C++ Russia).

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

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

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

В последние годы специализировался на велосипедостроении. Уровень мастерства в этом занятии можно оценить по easy_parser и easy_parser_router из RESTinio (на то, как это воплощено в коде, посмотреть можно здесь и здесь).

Составить впечатление о качестве моего кода можно здесь (timertt), здесь (so5extra) или здесь (atrataga). Именно эти разработки были сделаны практически в одиночку.

Могу сопровождать код документацией (см. Wiki для SObjectizer и so5extra, статьи на Хабре). Предполагаю, что умею связно излагать мысли в письменном виде, но это не точно.

Если кому-то интересно посмотреть на мое более развернутое резюме, то проще всего заглянуть в мой профиль на LinkedIn.

Чем я могу быть полезен вашему проекту и/или вашей компании:

  • в качестве консультанта по C++ или "играющего тренера" для вашей C++ной команды, если в ней мало опытных C++ников: проведение code review, объяснение почему тот или иной код опасен, прививание команде навыков написания более-менее идеоматического C++ кода (в том числе с учетом возможностей modern C++);
  • в качестве самостоятельного и автономного субконтрактора, который может создать для вас прототип нового решения и/или привести в нормальное состояние кусок старой кодовой базы;
  • в качестве члена проектной команды, работающего удаленно.

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

Рейт от 20 до 35 USD в час в зависимости от проекта. Чем ответственнее проект, чем более требовательны вы к гарантийным обязательствам, чем короче сроки, тем дороже.

Заранее предупрежу о своих недостатках чтобы не отнимать друг у друга время:

  • английский язык на уровне "читаю и перевожу со словарем" (как-то так). Вот уж чего не дадено, того не дадено;
  • не отношусь к числу тех, кто умеет все и берется за все. Если я чего-то не знаю или в чем-то не разбираюсь, то сразу говорю об этом. Вам решать готовы ли вы оплачивать мое погружение в нужную вам тему;
  • к работе подхожу вдумчиво и основательно. Из-за этого вы можете столкнуться с большим потоком уточняющих вопросов с моей стороны, а прогнозы по срокам работ могут иметь весьма широкий диапазон;
  • предпочитаю находить компромиссы и могу продолжать конструктивное общение даже в ситуациях, когда на исполнителя на повышенных тонах в нецензурной форме пытаются повесить всех собак, но политкорректностью не отличаюсь и рублю правду матку не взирая на лица и звания;
  • если вам нужен кто-то энергичный и способный резво махать шашкой в экстремальных условиях, то я вам точно не подойду. Когда случается пожар, все носятся с горящей жопой и никто не знает куда бежать, за что хвататься, то на вопрос "Ты ж программист, так какого хрена, а?" вы услышите от меня разве что "Дайте мне спокойно подумать";
  • обладаю специфическим чувством юмора, чрезмерной самоиронией и несерьезным отношением к самому себе;
  • врожденный NIH-синдром.

Если описанное выше вас устраивает, то связаться со мной можно через Telegram/WhatsUp/Viber по номеру +375-29-536-32-25 или по почте eao197 на stiffstream тчк com (более оперативно я доступен по eao197 на gmail).

четверг, 27 мая 2021 г.

[prog.c++] Оказывается, сложность нашего C++ного кода пытаются обсуждать на RSDN...

Вот так сидишь, тихо починяешь примус, а оказывается, что твое "творчество" обсуждают на профильном форуме: http://rsdn.org/forum/job/8017340

Лет семь назад, когда мы начинали активно рассказывать про SO-5 на просторах Интернета, меня достаточно сильно задевали реплики "не понятно", "слишкамсложна", "нахрена столько шаблонов" и "почему нельзя проще".

С годами к этому выработалось более спокойное отношение. Ибо C++ -- это язык, который вряд ли кто-то использует весь полностью. Как правило, выбирается некоторое подмножество, наиболее пригодное для решения задачи, и на нем уже решение и реализуется.

Поэтому в мире C++ сосуществуют и проекты на "Си с классами" и настоящий хардкор с 10-этажными шаблонами и самыми свежими нововведениями. А между двумя этими крайностями еще целый спектр вариантов.

Так что если кому-то кажется, что наши открытые проекты написаны слишком сложно, ну и что из этого?

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

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

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

И да, важный момент: если взять какой-то кусок кода или проектное решение из нашего OpenSource, то практически всегда можно будет обосновать почему было сделано так, а не иначе. Т.е. из все это было сделано не просто так, не от желания повыделываться или почесать ЧСВ, а с учетом условий и возможностей. Повторюсь, далеко не самых больших возможностей. Так что иногда мы делали максимально хороше решение из тех, что смогли придумать мы сами. А то, что кто-то смог бы придумать лучше, в этом даже сомнений нет.

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

среда, 19 мая 2021 г.

[prog.c++] Больше шаблонов богу шаблонов: детали реализации неоднозначной фичи, которая может стать частью json-dto

Где-то пять лет назад мы сделали небольшую библиотеку-обертку над RapidJSON: json-dto. Целью было снизить количество писанины при работе RapidJSON. Вроде бы у нас получилось:

#include <json_dto/pub.hpp>

#include <deque>
#include <set>
#include <map>

struct my_message {
   std::deque<int> ids_;
   std::set<std::string> tags_;
   std::map<std::string, some_another_type> props_;
   ...
   template<typename Json_Io>
   void json_io(Json_Io & io) {
      io & json_dto::mandatory("ids", ids_)
         & json_dto::mandatory("tags", tags_)
         & json_dto::mandatory("properties", props_)
         ...
         ;
   }
};

Библиотека открытая, но про нее мало кто знает. Тем удивительнее, ей пользуется еще кто-то кроме нас. По крайней до сих пор приходят запросы на добавление той или иной фичи в json-dto.

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

Человек захотел, чтобы можно было описывать поля объекта, которые подлежат только сериализации. Т.е. они участвуют при записи в JSON, а вот при десериализации из JSON их значения должны игнорироваться. Автор этого запроса даже сделал PR с реализацией фичи, которую он хотел получить в json-dto. Однако, предложенный вариант мне не понравился.

Данный пост посвящен рассказу о том, почему же PR не был принят в json-dto, что захотелось получить мне и что в итоге удалось придумать.

суббота, 15 мая 2021 г.

[prog.flame] Стабильному Rust-у исполнилось 6 лет

Шесть лет назад состоялся релиз "стабильной" версии Rust 1.0. Так что именно с 15-го мая 2015 года можно смело отсчитывать возраст языка программирования Rust.

Давеча в FB я уже высказался на эту тему. А данный пост можно рассматривать как расширенную и дополненную версию FB-шной заметки.

Революции не случилось

Главное, что хочется сказать в очередную годовщину выхода Rust-а в свет, -- это то, что Rust пока что не изменил ландшафт нашей софтостроительной индустрии.

суббота, 1 мая 2021 г.

[life.cinema] Очередной кинообзор (2021/04)

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

Аферистка (I Care a Lot, 2020). Весьма неплохо, смотреть было интересно.

Дикая (Wild, 2014). Хороший фильм. Меня неприятно удивило то, насколько невнятно в фильме показали уникальные по своей красоте места, которые попадали в кадр. Но это, наверное, уже придирка.

Никто (Nobody, 2021). Не впечатлил. Местами было скучно. Местами фрагменты фильма напоминали слишком затянутые видеоклипы. В сюжете никаких неожиданностей. В общем, не самая плохая попытка сделать бюджетный вариант "Джона Уика". Но именно что попытка. Глянуть можно, но чего-то выдающегося ждать не следует.

Взаперти (Run, 2020). Посмотреть можно, но общее впечатление такое, что достаточного бюджета фильму не выделили.

Выбивая долги (The Tax Collector, 2020). Занудная ерунда. Фильм, в котором никому не сочувствуешь и после просмотра жалеешь, что поубивали не всех. Шайа ЛаБаф, как актер, переиграл всех остальных актеров фильма вместе взятых, но его персонаж так и не "выстрелил", так что зачем в этот четверосотный фильмец зазвали такого мощного исполнителя я не понял.

суббота, 17 апреля 2021 г.

[prog.wtf] Пример творческого подхода некоторых софтописателей к трактовке спецификаций

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

Процедура подключения клиента к SOCKS5 серверу проста.

Клиент подключается и шлет первый PDU, в котором перечисляются методы аутентификации, поддерживаемые клиентом (например: без аутентификации вообще, на базе username/password).

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

Получив ответ от сервера клиент должен прислать следующее сообщение, в котором будут находится параметры для выбранного способа аутентификации. Так, если клиент и сервер договорились об использовании метода username/password, то во втором сообщении от клиент должны прийти username и password.

Итак, простая схема, в которой клиент шлет сообщение серверу, сервер отвечает, затем клиент шлет второе сообщение и т.д.

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

вторник, 13 апреля 2021 г.

[life.music] Продолжение саги о выборе хороших, но недорогих наушников на Aliexpress. Хороший звук за минимальный бюджет

Продолжаю делится впечатлениями от процесса поиска на Aliexpress недорогих, но хороших наушников. Делать обзор побывавших у меня наушников-вкладышей пока не готов (да и сомневаюсь, что это будет кому-то интересно). Поэтому сегодня расскажу о том, на что бы я сейчас, имея мой сегодняшний опыт, потратил бы деньги. Чтобы и хороший звук получить, и чтобы обошлось это в небольшую сумму, и чтобы не приходилось выходить за наш РБшный лимит в 25 USD за одну посылку.

Дисклаймер. Под хорошим звуком я понимаю звук, который устраивает меня. Т.е. когда я надеваю наушники, начинаю слушать музыку и меня перестает волновать через какие именно устройства я слушаю, какие у них характеристики, сколько они стоят и пр. Наверняка бывалые аудиофилы, профессионалы в обработке звука, да и просто люди с музыкальным слухом имеют совсем другое мнение по поводу понятия "хороший звук", но мне фиолетово :)

Главный фокус -- источник звука

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

Но гораздо меньше людей задумываются о том, что следующим важнейшим фактором является источник звука, т.к. устройство, которое и воспроизводит наш качественный MP3- или FLAC-файл. Я, например, на эту тему даже не задумывался. А зря.

понедельник, 12 апреля 2021 г.

[prog.c++] Наглядно на тему сложности освоения SObjectizer-а

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

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

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

О том, что SObjectizer где-то и как-то применяется мы узнаем, как правило, из двух источников:

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

И вот второй источник мало того, что дает нам информацию о том, что SObjectizer кто-то пробует, так еще и многое говорит о качестве и объеме справочной информации, которой мы снабдили SObjectizer. Поскольку по большей части это не вопросы из категории "у меня что-то не компилируется, почему?", а обращения за советом как быть в той или иной ситуации. Т.е. люди нашли SObjectizer, изучили его базовые принципы, попробовали что-то сделать, дошли до какой-то не самой тривиальной ситуации и только после этого решили спросить наше мнение.

Совсем свежий пример в Google-группе. Человек разобрался с SObjectizer-ом, сделал далеко не самый простой имитатор того, что ему нужно в его предметной области, и спросил совета по достаточно интересной и неоднозначной теме.

Так что SObjectizer -- это вовсе не "образцовое ненужно" (на смотря на то, что меня в этом настойчиво убеждают благожелатели в Интернетах). Этим инструментом интересуются, его пробуют, его используют.

То, что мы вынуждены приостановить работы над нашими OpenSource проектами (включая SObjectizer), не означает, что проект заброшен. Без поддержки, как можете видеть, пользователей не оставляем. Ну а как представится возможность, так и продолжим снабжать SObjectizer/so5extra и RESTinio новыми фичами.

четверг, 8 апреля 2021 г.

[prog.c++.bicycle] Отдельный тип для строковых литералов своими руками

Если я правильно понимаю, то в C и C++ строковые литералы хранятся в статической памяти. Поэтому указатель на строковый литерал остается валидным, фактически, до самого конца работы программы. Т.е. если мы пишем что-то вроде:

class long_living_object {
  const char * value_;
public:
  long_living_object(const char * v) : value_{v} {}
  ...
};

long_living_object make_object_ok() {
  return { "Hello, World!" };
}

то у нас, в принципе, все нормально. В возвращаемом функцией make_object_ok объекте будет находиться валидный указатель.

К сожалению, в C++ нет никакого способа отличить указатель на строковый литерал от указателя на какой-то временный массив символов. Т.е., ничто в языке не запрещает нам сделать так:

long_living_object make_object_bug() {
  char greeting[] = "Hello, World!";
  return { greeting };
}

Чтобы использовать объекты long_living_object было безопасно, нужно скопировать содержимое передаваемой строки вовнутрь. Что требует дополнительных ресурсов, особенно когда длина строки нам заранее неизвестна и мы вынуждены использовать динамическую память.

Все это особенно обидно в ситуациях, когда мы точно знаем, что long_living_object должен содержать указатели только на строковые литералы. Например, когда long_living_object -- это что-то вроде:

понедельник, 5 апреля 2021 г.

[life.music] Продолжение саги о выборе хороших, но недорогих наушников на Aliexpress. Отчет о побывавших у меня внутриканалках

Сегодня кратко пройдусь по моделям внутриканальных наушников, которые побывали у меня в руках. За исключением KZ ZSN Pro, с которых все началось и которые я благополучно продал еще в январе.

Прежде чем начать...

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

среда, 31 марта 2021 г.

[life.cinema] Очередной кинообзор (2020/03)

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

Фильмы

Девушка, подающая надежды (Promising Young Woman, 2020). Посмотрел случайно. Зашло на удивление хорошо. Главная моя претензия к фильму в том, что с исполнительницей главной роли угадали хорошо, но совершенно не верилось, что ей по фильму 30 лет. Если бы по фильму ей было 35, то и смотрелось бы более естественно, и то, что она так долго все это хранила в себе, придавало бы происходящему больше драматизма.

Последний богатырь: Корень зла (2020). Как по мне, так чуть слабее первой части, но все равно понравился. Для современного российского кино так прям очень здорово.

Марионетка (Marionette, 2020). Не так уж и плохо. Можно посмотреть.

Душевная кухня (Soul Kitchen, 2009). Странный фильм. Не берусь даже сказать к какому жанру его можно отнести, но смотреть было интересно.

Гениальное ограбление (Way Down, 2021). Лет 15 назад мог бы и зайти. А сейчас воспринимается как-то ну очень уж наивно и штамповано как-то, без изюминки.

В чужой шкуре (Possessor, 2020). Купился на достаточно высокий рейтинг этого фильма на IVI и Kinopoisk. Оказалась редкая муть. Такое ощущение, что снимали его сексуально озабоченные укурки. Хорошо хоть, что это были озабоченные гетеросексуалы, а то ведь могло быть и гораздо хуже. В общем, не хотите терять времени -- не смотрите.

Сериал

Кардинал (Cardinal, четыре сезона). Понравился. Смотреть было интересно. Хотя это как бы и не детектив вовсе. Скорее просто истории про людей в криминальном антураже.

вторник, 30 марта 2021 г.

[life.music] Продолжение саги о выборе хороших, но недорогих наушников на Aliexpress. Мое отношение к "тёмным" наушникам

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

Светлые vs темные

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

четверг, 25 марта 2021 г.

[prog.c++] Мне кажется, что с SObjectizer-ом гораздо лучше видно где, когда и какие треды создаются внутри приложения

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

Так вот, постепенно пришел к выводу, что помимо прочего в SObjectizer гораздо лучше видно сколько и каких рабочих потоков (тредов) создается, где и когда это происходит.

В SObjectizer ты имеешь дело с агентами. Агенты сами никаких нитей (тредов) не запускают. Такими вещами занимаются диспетчеры.

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

Тогда как изучая код, использующий голую многопоточность, приходится обращать внимание на то, где появляются экземпляры std::thread (или какие-нибудь самодельные обертки над POSIX Threads). Зачастую такие экземпляры являются членами какого-то класса. Типа service_manager или session_listener. И стартуют/останавливаются рабочие нити в каких-то методах этих самых service_manager/session_listener/им-подобных-классов. Что не так-то и просто обнаружить. А обнаружив потом еще и держать в памяти: "О, вот этот объект запустил рабочую нить, а затем этот объект переходит в подчинение вот этому, а нить останавливается тогда, когда..."

В общем, привыкаешь к хорошему (это я про SObjectizer), расслабляешься, теряешь нюх на неприятности... :(

вторник, 23 марта 2021 г.

[life.music] Продолжение саги о выборе хороших, но недорогих наушников на Aliexpress. Пару слов о самом выборе

Во второй части попробую рассказать об аспектах, которые имеет смысл принимать во внимание при выборе наушников.

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

Какие-то аспекты (вроде съемного кабеля) наверняка будут лишь дополнительным фактором.

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

Поскольку вся эта серия посвящена закупке наушников на Aliexpress, то и картинки для иллюстраций я без зазрения совести утащил именно оттуда.

пятница, 19 марта 2021 г.

[prog.c++] Видео доклада Николая Гродзицкого про SObjectizer на виртуальном митапе Italian C++ Community

Мой коллега, Николай Гродзицкий, сделал доклад про SObjectizer на митапе Italian C++ Community. Видео этого доклада уже доступно на YouTube. Между прочим, знаменательное событие -- первый доклад про SObjectizer на английском языке на международную аудиторию.

Слайды доклада доступны здесь.


Думаю, что можно рассказать историю появления этого доклада. Где-то в январе в репозитории SObjectizer-а на GitHub-е начал создавать issues некто Марко Арена. Из его пояснений получалось, что он вынужден портировать под Linux софт, написанный на базе Microsoft PPL. И этот самый PPL ему нужно чем-то заменить, поэтому он пробует SObjectizer. В каком-то из issues я его попросил, мол, будет большая помощь проекту, если Марко поделится ссылкой на SObjectizer в своих соцсетях. На что он сказал что-то вроде: "Да не вопрос, но можно сделать и лучше. Я веду Italian C++ Community, мы раз в месяц проводим митапы с докладами на разные темы. Не хотите ли сделать у нас доклад про SObjectizer?" Мы, естественно, захотели.

Огромное спасибо Николаю за то, что взял на себя смелость и прочитал этот доклад на английском.

четверг, 18 марта 2021 г.

[peopleware] Сколько людей -- столько и мнений

Вчера днем какой-то анонимный надмозг с LOR-а в очередной раз утверждал, что я делаю никому не нужные хелловорлды. Подозреваю, что он имел в виду именно SObjectizer и RESTinio.

Вчера же вечером, когда мой коллега, Коля Гродзицкий, читал доклад о SObjectizer-е на виртуальном митинге Italian C++ Community, Марко Арена, несколько месяцев назад самостоятельно нашедший SObjectizer и начавший его использовать для своих задач, сказал, что у SObjectizer-а одна из самых лучших Wiki, что доводилось видеть в OpenSource проектах.

PS. Если я правильно понимаю, то упомянутый мной Марко Арена портирует под Linux приложение, написанное на базе Microsoft-овской PPL. И как раз SObjectizer-ом он заменяет PPL.

воскресенье, 14 марта 2021 г.

[life.music] Введение в сагу о выборе недорогих, но хороших наушников на Aliexpress

Люди, которые подписаны на меня в FB, уже в курсе того, что я умудрился вписаться в странный эксперимент над собственным кошельком: назаказывал кучу разнообразных наушников с Aliexpress в попытке подобрать для себя те, которые будут устраивать меня по звучанию, но при покупке которых получится уложиться в лимит $25 на одну посылку.

Для тех же читателей, которые пока что не в курсе данной истории, расскажу что к чему и откуда растут ноги.

четверг, 11 марта 2021 г.

[prog.c++] Наглядно про "могу помочь вашей команде улучшить качество кода"

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

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

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

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

среда, 3 марта 2021 г.

[business.mistake] Проиллюстрирую свои недостатки, пожалуй...

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

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

Преамбула

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

Речь зашла о том, что им нужно быстро сделать обработку графа социальных связей. Проблема из категории тех, которые решаются в FB, VK, Twitter, Instagram, LinkedIn, когда нужно формировать и обновлять ленту новостей у пользователя. На масштабах, которые поменьше, чем у вышеозначенных соцсетей, конечно, но в пределе виделось несколько сот миллионов пользователей у некоторых из которых могут быть миллионы контактов.

понедельник, 1 марта 2021 г.

[life.cinema] Очередной кинообзор (2021/02)

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

Фильмы

Дьявол в деталях (The Little Things, 2021). Если бы не очень уже специфическая (я бы даже сказал укуренная) манера повествования, то мне бы даже могло очень понравится. А так просто неплохой фильм получился, можно посмотреть.

Охотник на монстров (Monster hunter, 2020). Да, тупо. Да, фэнтези. Но бодренько и красочно. На фоне выходящего в последнее время шлака даже ничего себе так. Хотя, конечно, далеко не первая "Обитель Зла".

На Луне (2019). Фильм, состоящий из одних штампов и шаблонов. Но снят хорошо и для современного российского кино он выглядит просто замечательно.

Зависнуть в Палм-Спрингс (Palm Springs, 2020). Еще одна итерация вокруг темы "Дня сурка". Вполне можно посмотреть.

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

Остров фантазий (Fantasy Island, 2020). Средней паршивости. Есть ощущение, что не хватило бюджета для создания нормальной картинки в нужных местах.

Космос (Cosmos, 2019). Угораздило посмотреть. Сначала было интересно, что же авторы этой явно бюджетной ленты вставят в этот фильм такого, чтобы оправдать жанр "фантастика". Хотя уже с самого начала было много намеков на то, что ничего хорошего ждать не следует. А уж в финале кино скатилось в какой-то невероятный трэш вперемешку с убогим пафосом. В общем, смотреть не рекомендую.

Афера Оливера Твиста (Twist, 2021). Низкобюджетный и низкопробный английский телефильм, после просмотра которого возникает один вопрос: как туда удалось затащить Майкла Кейна?

Огонь (2020). Редкая по накалу идиотии очередная попытка снять "наш ответ Голливуду". Местами вроде как и нормально, но местами такая муть (вроде родов в автобусе на горящем мосту), что можно убить себя фейспалмами. Ну и картинка пожаров такая, что у авторов фильма невольно хочется спросить: "А вы когда-нибудь хотя бы у костра среднего размера пробовали постоять?"

Сериал

Фортитьюд (Fortitude, первый сезон). Первые 2/3 смотреть было интересно. Но финал первого сезона как-то совсем уж уныло и бездарно слили. Поэтому желания смотреть последующие сезоны не возникло.

четверг, 25 февраля 2021 г.

[prog.flame] Тесты как показатель качества?

Сегодня хочется поговорить об одном найденом на просторах Twitter-а высказывании:

В FB уже немного обстебал это изречение. Но тема поднята такая, которую можно обсудить и вполне себе серьезно.

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

Итак:

Качество -- это оценка ценности некоторого изделия.

Тест -- это оценка пригодности некоторого изделия к выполнению своей основной функции (одной из функций).

Соответственно, качество и тесты -- это про разное.

А теперь позвольте растечься мыслею по древу...

среда, 10 февраля 2021 г.

[prog.c++] Куда не заглянешь, везде чего-нить да унюхаешь...

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

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

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

Приведу пару свежих примеров.

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

[soft.process] Погружение в Agile: так есть ли в этом всем смысл?

Пожалуй, нужно подвести итог темы, начатой в ноябре прошлого года. Про Agile и непрекращающийся шум вокруг него.

Начитался и наслушался тут разного. И, похоже, сложилось у меня некоторое мнение. Уж не знаю, стоит выносить его на публику, но попробуем.

Итак, Agile есть и он работает. Действительно.

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

вторник, 2 февраля 2021 г.

[soft.business] Послесловие к неудачной попытке найти внешнее финансирование для RESTinio/SObjectizer/so5extra

На данный момент история с поиском финансирования закончилась ничем. Развитие наших OpenSource-проектов приостановлено. Попробуем поднакопить средства на заказной разработке/консультациях, чтобы затем вернуться к работам над RESTinio/SObjectizer/so5extra.

А в этом послесловии просто расскажу на что был расчет когда писался пост о поиске внешнего финансирования, может кому-то пригодится наш опыт.

Суть в том, что у SObjectizer-а и у RESTinio совершенно разные ситуации.

SObjectizer старый и устоявшийся программный продукт. Далеко не самый популярный и известный. Если его следующий релиз выйдет в конце 2021-го или даже в начале 2022-го, то отрицательно на SObjectizer-е это вряд ли скажется. А если и скажется, то не сильно.

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

В конце 2020-го года мы попали в ситуацию, которая, по хорошему, требует оперативного разрешения: проект http-parser, использующийся в RESTinio, остался без сопровождения. Соответственно, чтобы не зависеть от проекта без поддержки, RESTinio нужно сменить парсер HTTP-протокола на что-то другое.

Добавим сюда еще и то, что для успешной конкуренции с аналогичными проектами RESTinio очень желательно было бы иметь поддержку не только http/1.1, но и хотя бы http/2.

И если уж менять http-parser на что-то другое, то можно было бы под этим соусом добавить в RESTinio и http/2. А если получится, то и заложить возможность последующего добавления http/3.

Сложно сказать, во что бы это все вылилось по трудозатратам. Но по первым впечатлениям, от 3 до 5 месяцев это могло бы занять. Тут нужно учитывать, что мы стараемся тщательно тестировать RESTinio, писать примеры и расширять документацию. Это такая работа, которая может быть не видна, но которая должна быть выполнена, и которая занимает изрядное время. Поэтому если кому-то кажется, что 3-5 месяца для написания собственной поддержки http/1.1 и http/2 -- это слишком много, то мне лишь остается позавидовать вашей производительности и трудолюбию.

Итого, если начать работы над RESTinio-0.7 сейчас и вести их не отрываясь ни на что другое, то выкатить новую версию получится лишь где-то к лету 2021-го.

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

Мы встали перед выбором: либо заняться заказной разработкой и остановить развитие RESTinio на какое-то время, либо же поискать внешние вложения.

Остановка развития RESTinio выглядела слишком рискованно. Сперва RESTinio будет заморожен на 5-6 месяцев, затем в течении еще 3-5 месяцев будет вестись разработка новой версии с релизом RESTinio-0.7 где-то через год... Отличная перспектива чтобы закопать проект.

Поэтому мы решились на поиск внешнего финансирования.

Фактически, мы пошли с протянутой рукой. Мол, сами мы не местные, помогите кто чем может.

Варианты с платной техподдержкой и "рекламными услугами" были выбраны по следующим причинам:

1. В РБ (да и в РФ) нельзя просто так взять и внести деньги на счет коммерческой структуры. Поступление денег должно быть оформлено договором. Лучше всего, если это договор на оказание каких-то услуг или на выполнение каких-то работ. Техподдержка и "рекламные услуги" как раз и являются теми формами договорных отношений, которые позволяют нам получать деньги ровно за то, что мы и делаем. И не требуют от нас ничего больше, за исключением оформления некоторого количества дополнительных бумажек раз в квартал (в виде актов по выполненным работам).

2. Суммы мы выбрали такие, которые крупные (и даже не очень крупные) компании могут выложить не задумываясь. Грубо говоря, в компании с несколькими тысячами сотрудников 150USD в квартал отдел маркетинга может запросто потратить просто "на скрепки". Мы надеялись, что сумма в 600USD в год для крупного производителя софта будет достаточно мизерной для того, чтобы ответственные люди могли дать добро на помощь нашим открытым проектам не заморачиваясь на то, что мы можем дать взамен.

Если же называть вещи своими именами, то мы рассчитывали на благотворительность.

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

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

Так что попробуем вариант с заказной разработкой. Посмотрим, что из этого выйдет. Пост о том, какие именно ресурсы мы можем выставить на рынок труда опубликую в ближайшие пару дней. Upd. Собственно, вот.

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

PS. Если какая-то компания хочет вложиться в разработку RESTinio/SObjectizer/so5extra (например, хочет поиметь какую-то специфическую функциональность), то давайте пообщаемся на eao197 на gmail тчк com. Можно обсуждать различные варианты сотрудничества.

воскресенье, 31 января 2021 г.

[life.cinema] Очередной кинообзор (2021/01)

Пришло время сделать очередной кинообзор. Как обычно, в начале списка идут фильмы, которые понравились больше, а в самом конце откровенный шлак, на который можно не тратить свое время.

Охота на Санту (Fatman, 2020). Мне лично зашел ну очень хорошо. Показалось, что это очень тонкий стеб на сугубо американские темы. Но некоторые из них оказались понятны даже мне (например, поручение сборки панелей для нового самолета эльфам).

Неадекватные люди 2 (2020). По сравнению с другим современным российским кино так прямо отличный фильм. Но к первой части имеет косвенное отношение.

Гудбай, Америка (2020). Неплохая задумка и даже некоторые актеры пытаются играть. Но в целом унылое впечатление. Те же хорошие актеры, которые пытаются играть, явно демонстрируют, что все остальные в фильме занимаются не пойми чем. Многие сцены выглядят так, как будто актеров приодели и "наштукатурили" для рекламной съемки для глянцевого журнала, а вместо этого заставили что-то играть. Из-за чего гламурный и напомаженный вид персонажей в тех или иных сценах заставляет вспомнить незабвенное "Не верю!" В общем, о просмотре не жалею, но и рекомендовать не могу.

Не входи (The Owners, 2020). При хорошей идее и даже старательных попытках ее воплощения авторы явно недокрутили. Так что нормально не вышло. Мне показалось, что слишком уж много странных и нелогично ведущих себя персонажей, плюс некоторые линию сюжета толком не были объяснены. Если уж совсем нечего смотреть, то можно глянуть, но ждать многого не следует.

Чудо-женщина: 1984 (Wonder Woman 1984, 2020). До просмотра ожидал две вещи: что на Галь Гадот в бронелифчике будет приятно смотреть и что от сюжета не следует чего-либо ждать. Не обманулся. Но к этому совершенно неожиданно добавился совершенно дешманский уровень спецэффектов. Что превратило кино в откровенный отстой. И даже красота Галь Гадот ничего не смогла с этим поделать.

Монстры, созданные человеком (Monsters of Man, 2020). Затянутый и откровенно дешевый. Но, как это не странно, производит более хорошее впечатление, чем гораздо более дорогой фильм "Смертельная зона" от Netflix (см.ниже).

Плохие парни навсегда (Bad Boys for Life, 2020). Начало было довольно пристойным и даже вселяло надежду на нормальное кино, но вторая половина фильма скатилось в такое редкостное говно, по сравнению с которым даже болливудские боевики смотрятся почти как документальные.

Смертельная зона (Outside the Wire, 2021). Редкостная дрянь. А деньги на визуальные эффекты, такое ощущение, тупо распилили.

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

[soft.business] Ищу финансирование для развития RESTinio/SObjectizer/so5extra

Наша совсем маленькая компания stiffstream на протяжении нескольких лет делает такие OpenSource инструменты для С++ как:

  • RESTinio: встраиваемый HTTP/WebSocket сервер, ориентированный на эффективную асинхронную обработку входящих HTTP-запросов;
  • SObjectizer/so5extra: реализация Actor Model, Publish-Subscribe и Communicating Sequential Processes, существенно упрощающая разработку сложных многопоточных приложений.

Прибыли эти разработки не приносят, мы вели их за свои деньги.

К сожалению, кризис 2020-го ударил и по нам. Наши собственные финансовые ресурсы для развития RESTinio и SObjectizer/so5extra практически исчерпаны.

Поэтому мы приостанавливаем работы над этими проектами на неопределенный срок.

UPD. На данный момент история с поиском финансирования закончилась ничем. Развитие наших OpenSource-проектов пока приостановлено. Мы попробуем поднакопить средства на заказной разработке/консультациях, чтобы затем вернуться к работам над RESTinio/SObjectizer/so5extra. Кому интересно, вот послесловие к этой затее.

Соответственно, те предложения, которые были первоначально описаны в этом посте, стали не актуальны. Я спрятал их под кат, сохранив просто для истории.

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

[prog.c++] Текущие хотелки по SObjectizer/so5extra

Две недели назад был пост о том, что хотелось бы поиметь в RESTinio. Попытаюсь сформулировать что-то подобное и в отношении SObjectizer+so5extra.

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

На данный момент я вижу два направления, в рамках которых можно произвести НИОКР и, если в сухом остатке получится приемлемый результат, перенести результаты исследований в SObjectizer.


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

Суть в том, что сейчас агенты в SObjectizer-е работают в соответствии с push-моделью.

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

Push-модель проста, понятна, эффективна и подходит для огромного количества случаев.

Однако бывают моменты, когда агенту выгоднее использовать pull-модель.

Первый сценарий, который можно закрыть посредством pull-модели -- это поддержка приоритетов для заявок (см. недавнюю статью на Habr-е на эту тему). Причем такая поддержка, которая бы позволила использовать приоритеты заявок совместно с базовыми штатными диспетчерами SObjectizer-а, которые изначально для этого вообще не предназначались (например, one_thread, active_obj, active_group, thread_pool, а также asio_thread_pool и asio_one_thread из so5extra).

Второй сценарий -- это еще одно возможное решение проблемы producer-consumer, которое давеча обсуждалось в issue на GitHub-е. Идея в том, что специализированный mbox собирает отосланные в него сообщения, но не сразу отсылает сообщения в очереди событий агентов, а хранит у себя до тех пор, пока какой-то из consumer-ов не освободится и не обратиться за следующим сообщением. В этом случае pull-модель выглядит предпочтительнее push-модели.

Третий сценарий -- это возможность агента читать сообщения напрямую из mchain-а как из обычного mbox-а. Дело в том, что mchain-ы задумывались как средство передачи информации от агентов наружу, в те части приложения, которые написаны без SObjectizer-а (в обратную сторону отлично работают старые-добрые mbox-ы). И в этом качестве они работают отлично. Но иногда их хочется использовать и для общения агентов между собой. А вот тут не все так хорошо, поскольку нет простого и эффективного способа проинформировать агента, заинтересованного в чтении сообщений из mchain-а, о том, что в mchain-е есть информация и можно вызывать receive.

Так что желание подружить агентов и mchain-ы у меня лично есть уже давно, а вот четких мыслей о том, как это сделать, пока не было. Возможно, эксперименты с pull-моделью помогут.

Четвертый сценарий -- это возможность сделать поддержку чего-то вроде selective receive (например, по аналогии с механизмом Stash из Akka). Правда, я не уверен, что это действительно реализуемо. Но, думается, что pull-модель предоставляет здесь несколько больше шансов на успех, нежели push-модель.

В общем, направление многообещающее, но, к сожалению, требующее некоторых исследований и экспериментов. А посему на выходе вполне можно получить и отрицательный результат, который будет вполне себе результатом, который укажет, что в рамках SO-5 это недостижимо.


Второе направление -- это предоставление возможности пользователю создавать свои экземпляры рабочих нитей в штатных диспетчерах.

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

Временами это не есть хорошо. Например, если пользователь хочет создать 100500 агентов, привязанных к active_obj-диспетчеру (т.е. работающих на собственных рабочих нитях), но при этом желает ограничить размер стека для каждой из рабочих нитей всего 32KiB. Работай пользователь напрямую с POSIX threads у него была бы такая возможность. А вот штатные диспетчеры не позволяют это сделать.

Другой сценарий: пользователь хочет поиграться с приоритетами рабочих нитей. Например, создать one_thread-диспетчер с высоким приоритетом рабочей нити. И thread_pool-диспетчер с низкоприоритетными рабочими нитями. Опять же, на чистом POSIX threads API это можно было бы сделать. А через штатные диспетчеры SO-5 -- нет.

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

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

Нужно сказать, что диспетчеры asio_one_thread и asio_thread_pool из so5extra позволяют в свойствах диспетчера задать тип для рабочей нити. Так что эти два диспетчера позволяют пользователю реализовывать рабочие нити вручную со всеми нужными свойствами, тогда как основная внутренняя логика работы диспетчера остается на нашей (т.е. мейнтенеров SO-5) совести.

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


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

Так что если вы хотели бы видеть что-то в SObjectizer-е, что могло бы облегчить вам вашу работу, то скажите об этом нам. Например, через issues или discussions на GitHub-е.

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


Наверное, немного странно записывать хотелки когда вопрос о финансировании работ для наших OpenSource проектов еще не решен. И непонятно когда мы сможем вернуться к работе над RESTinio/SObjectizer.

Но, во-первых, этот пост нужен мне самому как "зарубка на память". Будет от чего оттолкнуться когда представится возможность вернуться к SObjectizer-у.

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

[work.opensource.c++] arataga: что это вообще и зачем мы публикуем это в OpenSource?

arataga -- это работающий прототип socks5+http/1.1 прокси сервера, который мы в прошлом году разрабатывали для одного из наших клиентов. К сожалению, этот прототип остался невостребованным. Ну а чтобы не пропадать добру и самопиара ради, мы решили открыть его исходники.

Как все развивалось

Дело было так: с 2019-го года мы работали с заказчиком, который эксплуатировал у себя некий старый прокси-сервер. Весьма старый, написанный с применением модели thread-per-connection, да еще и оставшийся без сопровождения. Собственно, мы как раз и занимались его доработкой под нужды заказчика.

Где-то к концу весны 2020-го стало понятно, что больше ничего хорошего из этого прокси-сервера не выжать. Что нужно его заменять на что-то новое, написанное с нуля или же переделанное готовое (типа nginx или envoy после обработки напильником).

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

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

Что стало неприятным сюрпризом, тем более, что до этого никаких проблем с заказчиком не было. И даже по ходу работ над arataga мы взаимодействовали по другим вопросам и он оплачивал нам сделанные ранее работы.

Наши обязательства перед клиентом закончились. У нас на руках остался arataga и с этим нужно было что-то делать. Например, выбросить и забыть. Или же открыть.

Зачем нужно было делать arataga?

У заказчика были следующие и, как мне представляется, местами весьма специфические условия:

четверг, 21 января 2021 г.

[life] Никто не знал, а я тормоз :)

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

Суть в том, что я с детства считал себя человеком, который думает быстро. Не знаю, с чем это связано. Может быть с тем, что сложные предметы в школе давались легко. Может быть потому, что если начинал заниматься чем-то, что мне нравилось, то быстро прогрессировал. Может быть на меня сильное впечатление произвела фраза Юлия Цезаря "Veni, vidi, vici". Вот не знаю.

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

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

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

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

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

Внезапно (c), да.

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

Самое трудное при таком подходе -- это как-то прервать процесс размышления на волнующую тему. Особенно когда какая-то внезапная мысль приходит посреди ночи. Готовых и 100% работающих рецептов пока нет. Были бы, поделился бы.

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

Какой вывод из всего сказанного?

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

суббота, 9 января 2021 г.

[prog.c++] Пару слов про позиционирование RESTinio и основные хотелки для RESTinio на 2021-й

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

ИМХО, уже пришла пора более точно определиться с позиционированием RESTinio в экосистеме C++. Это раньше RESTinio был молодой и мало кому известной разработкой. Сейчас же ситуация меняется, мы уже не молоды ;)

Позиционирование важно потому, что на данный момент можно насчитать с дюжину подобных инструментов для C++. И хотя на слуху находится всего пара-тройка названий, но если какой-то C++ разработчик захочет подобрать встраиваемый HTTP-сервер под свою задачу, то у него будет приличный выбор на любой вкус, цвет и размер кошелька. Конкурировать со всеми и во всех направлениях бессмысленно. Посему следует обозначить нишу для RESTinio.

Мне представляется, что RESTinio уникален тем, что под одной крышей здесь собрано:

  • простота использования RESTinio для каких-то очевидных и понятных действий. Так, чтобы получить запрос и пройтись по списку HTTP-полей, не нужно выписывать вручную процедуры чтения данных из сокета;
  • гибкая настройка RESTinio под условия пользователя. Захотел пользователь применять Boost.Log для логирования? Нет проблем, RESTinio позволяет написать адаптер и RESTinio будет логировать свои действия с помощью этого адаптера. Или, например, захотел пользователь запускать вместе с RESTinio на io_context еще и какие-то свои сетевые операции... Опять же, нет проблем;
  • набор инструментов, которые позволяют применять RESTinio для каких-то нетривиальных сценариев. Например, средства работы с HTTP-заголовками используются в arataga даже для исходящих HTTP-запросов.

Что делает RESTinio хорошим выбором для ситуаций, когда разработчику нужно что-то сильно повыше уровнем, чем Boost.Beast, но при этом хочется иметь гораздо больший контроль за происходящим, чем в oat++ или cpp-httplib.

Отличный пример такой задачи, на мой взгляд, -- это прокси-сервер типа arataga. На Boost.Beast его делать будет слишком хлопотно. А oat++/cpp-httplib вряд ли дадут доступ к своим потрохам.

Именно в этом направлении, думаю, и стоит развивать RESTinio дальше.

Т.е., RESTinio должен быть выше уровнем, чем Boost.Beast, но ниже, чем oat++ и cpp-httplib. Но при этом средствами RESTinio продвинутый разработчик с небольшими усилиями должен уметь создать для себя что-то похожее на oat++/cpp-httplib, но заточенное под специфические требования конкретной прикладной задачи.

Или же, в более лаконичной форме:

RESTinio должен стать конструктором из продвинутых инструментов, отлично подогнанных друг к другу.

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


Теперь попробую обозначить несколько приоритетов в предполагаемом развитии RESTinio в 2021-ом году.

Во-первых, это замена http_parser на что-то другое. Конечно же, хочется иметь собственную реализацию, которая бы a) сделала RESTinio полностью header-only библиотекой, и b) поддерживала бы различные тонкие моменты в HTTP-протоколе (вроде chunk extensions). Если это не получится, то рассмотреть и внедрить какую-то готовую альтернативную реализацию (llhttp, picohttpparser, что-то еще).

Во-вторых, добавление режима работы в котором RESTinio не будет загружать весь запрос в память перед вызовом обработчика, а будет отдавать читаемые от клиента данные кусками по мере их поступления. Это позволит a) эффективно обрабатывать запросы с большим объемом входящих данных, и b) использовать RESTinio для сценариев, в которых сейчас RESTinio не может применяться в принципе (например, для разработки прокси-сервисов).

В-третьих, добавление поддержки http/2. Пока RESTinio жестко завязана на работу со всего лишь один протокол. От этого нужно уходить, т.к. рано или поздно, http/2 и http/3 вытеснят http/1.1. И если в 2021-ом получится изменить RESTinio так, чтобы в нем поддерживалось сразу два протокола, то это откроет отличную возможность добавить со временем еще и http/3, а может и еще что-нибудь.

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

По поводу поддержки в RESTinio клиента я могу лишь повторить то, что уже говорил раньше: без внешнего финансирования мы поднять такую задачу не сможем. Так что если кто-то готов вложить в RESTinio, минимально, 3.5K USD, то давайте всерьез обсудим такую возможность.


Если кого-то интересует перечень встраиваемых HTTP-серверов для C++, то выглядит он приблизительно так (перечисление в случайном порядке): RESTinio, Boost.Beast, cpp-httplib, http_backend, Pistache, RestBed, served, C++ REST SDK, proxygen, Simple-Web-Server, drogon, oat++