пятница, 26 июля 2024 г.

[dev.hiring.flame] Посмотрел и разоблачение Антона Назарова и реакцию на это разоблачение от самого Антона Назарова

Продолжение и, надеюсь, завершение недавней темы. В догонку к ролику от HR-а про "волков" и "волчат" (далее "HR-овский ролик") осилил и стрим, на котором Антон Назаров смотрит и реагирует на "HR-овских ролик" (далее "волчий стрим").

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

Конечно же, авторы первого, "HR-овского ролика", откровенно подставились. Была попытка в сатирическом ключе разоблачить Антона Назарова и в его лице все явление накрутки опыта и обмана собеседующих. Хотели выступить стиле BadComedian, по факту вышло на уровне конкурса художественной самодеятельности 7-го класса общеобразовательной школы, если не ниже.

Чем и воспользовались Антон со своим соведущим по стриму -- с удовольствием обстебали ролик Леси и Глеба, причем, местами, вполне себе успешно и по делу.

При этом смотреть запись стрима с Антоном и Никитой мне было тяжело и вызывало когнитивный диссонанс: с одной стороны, два малолетних гопника с соответствующими манерами и лексикой, с другой стороны, вроде как с мозгами и эрудицией. Кстати говоря, посмотрев телеграмм соведущей "НR-овского ролика", Леси Набока, и попробовав посмотреть еще одно видео с ее канала "Два стула", у меня сложилось впечатление, что Леся такой же "малолетний дебил гопник" (вот в качестве иллюстрации один из постов, который зачем-то был написан с использованием нецензурных выражений). Так что, к сожалению, "борьба была равна, сражались два говна".

На "волчьем стриме" правильно отметили: "HR-овский ролик" оказался откровенной рекламой сообщества "Осознанная меркантильность". Ведь Назаров и Ко декларирует что? Существующая система найма имеет ряд серьезных недостатков из-за которых целые категории соискателей испытывают проблемы с поиском работы. А раз так, то плохую систему не грех и хакнуть. Чем Назаров и Ко и занимаются. И если HR-ы снимают длинные разоблачительные ролики, значит хакают успешно. Значит "волки" все делают правильно.

Что меня искренне удивило в "волчьем стриме", так это непонимание того, чем же деятельность "волков" вредит индустрии. Поэтому вот мое видение:

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

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

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

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

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

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

Пара серьезных недостатков текущей системы, на мой взгляд:

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

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

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

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

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

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

На меня Антон Назаров производит впечатление пены, образовавшейся на гребне волны интереса к ИТ. Сунулся в программизм, ничего не достиг, понял, что ему это не нравится, сумел найти и оседлать хайповую на данный момент тему. Ну OK, молодец, если главный талант -- это складно трындеть, то зачем зарывать его в землю и горбатиться над кодом?

В качестве звиздуна-собеседника на YouTube он, в принципе, хорош. Гораздо мощнее оппонирующей ему Леси Набока, кстати говоря.

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


В общем, чего хочу сказать:

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

вторник, 23 июля 2024 г.

[prog.c++] Как в json_dto можно сделать так, чтобы элемент в JSON был либо единичным объектом, либо вектором объектов?

В проекте для текущего заказчика возникла потребность сделать так, чтобы элемент в JSON-е мог быть либо одиночным объектом:

{
  "message": {
    ...,
    "extension": { ... }
  }
}

либо же вектором объектов:

{
  "message": {
    ...,
    "extension": [
      { ... },
      { ... },
      { ... }
    ]
  }
}

Сделать это оказалось не сложно, т.к. в проекте для работы с JSON используется весьма низкоуровневый инструмент, в котором, как в RapidJSON, приходится вручную разбираться с типами элементов. Буквально что-то вроде item.SetObject("extension", value) или item.SetArray("extension").PushBack(...).

Но мне стало интересно, а можно ли будет сделать что-то подобное с помощью нашей разработки json_dto.

Мы делали json_dto как раз для того, чтобы не нужно было вручную возиться с SetObject и SetArray, чтобы сериализатор/десериализатор сам разбирался с этой скучной рутиной. А такая высокоуровневость временами выходит боком, когда пытаешься сделать что-то, что изначальным дизайном библиотеки не предусматривалось. Так что я подумал, что это своего рода "вызов" и попробовал сделать такой трюк средствами json_dto.

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

Есть у нас в json_dto такое понятие, как кастомный Reader_Writer -- это объект с двумя методами, read и write. Именно этот объект берет на себя ответственность за то, чтобы прочитать/записать значение поля объекта посредством RapidJSON. По умолчанию для это делает сам json_dto, но когда нужно что-то кастомизировать, то пользователь может реализовать собственный Reader_Writer и приказать json_dto использовать именно этот Reader_Writer.

Как же это все выглядит?

понедельник, 22 июля 2024 г.

[dev.hiring.flame] Посмотрел давеча на YouTube ролик про "волчат" и "волков"

Вот это видео:

Да, там почти два часа, но смотреть интересно (хотя бы потому, что видно как сильно полыхает у ведущих).

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

Это понятно, это естественно, от этого не уйти.

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

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

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


Этот ролик заставил вспомнить ощущение, которое у меня сложилось лет 20 назад, где-то 2004-2005гг, когда у нас в РБ окончательно победил аутсорс (долгое время белорусский ИТ был заточен на аутсорс чуть меньше, чем полностью, а может и сейчас остается таким же).

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

Не уверен, что это впечатление было верным, но вот такое оно у меня было.

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

Да и сама ситуация, когда мне с 30-летним опытом, доступными на github-е проектами, кучей статьей и несколькими выступлениями на конференциях, нужно проходить секции live-coding-а с условным разворотом условной строки, не кажется нормальной.

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

Понимаю, но все равно нормальной эту ситуацию назвать не могу.

воскресенье, 21 июля 2024 г.

[life.audiophilia.diy] Итоговые впечатления от 15.4mm динамиков с литиево-магниевой диафрагмой

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

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

Как по мне, динамики дают "серединистый" звук, в котором НЧ и ВЧ заметно теряют громкость. Из-за чего у наушников получается непревзойденное трехмерность. По крайней мере в сравнении с тем, что есть у меня на руках.

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

Изначально в этих динамиках мне сильно не хватало веса на НЧ. Наушники были слишком "светлыми", хотелось большее баса.

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

В общем, с количеством НЧ смирился. А уж к качеству НЧ так вообще вопросов не было.

Засада же оказалась с ВЧ.

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

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


Основными для меня в последние месяцы продолжают оставаться 15.4mm динамики с DLC и LCP диафрагмами. Причем, если раньше и DLC, и LCP мне казались недостаточно басовитыми, то сейчас LCP ощущаются просто как басхэдные со слишком большим количеством слегка "ватного" баса. DLC же, которые раньше ощущались, как "светлые" в сравнении с LCP, теперь кажутся практически тем, "что доктор прописал". Хотя по четкости и жесткости проработки НЧ, наверное, DLC уступают описанным выше литиево-магниевым динамикам, но компенсируют массой и громкостью НЧ.

Иногда слушаю и откровенно бюджетные 15.4mm динамики с композитной бериллиевой диафрагмой. Они хоть и бюджетные, с чрезмерной (для меня сейчас) массой НЧ, и "проваленной" серединкой, но зато с совершенно шикарными для своей цены ВЧ. Есть что-то в этих динамиках такое, что в первые два-три дня прослушивания невероятно очаровывает. Потом, правда, от количества НЧ устаешь и возвращаешься к DLC/LCP. Чтобы еще через месяц-два опять на пару дней вернутся к этому темному звуку с отличной детализацией на НЧ.

суббота, 20 июля 2024 г.

[life.business] Чего только в жизни не бывает...

Увидел некоторое время назад в ленте LinkedIn:

До сих пор пребываю в растерянности.

С одной стороны, очевидно, что 30 лет своей профессиональной деятельности занимался какой-то фигней. Мягко говоря.

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

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

понедельник, 1 июля 2024 г.

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

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

Фильмы

Однажды в Ла-Рое (LaRoy, Texas, 2023). В принципе мне нравится такое. Но тут лично меня разочаровал финал. Даже не знаю почему, но вот разочаровал. Поэтому не получается оценить этот фильм высоко. Но на мой вкус вполне себе крепкий середнячок. Получше многих современных "фильмов".

Падение империи (Civil War, 2024). Кино довольно посредственное, а общее отношение к нему будет зависеть от ожиданий: если ждать, что это рассказ о гипотетической гражданской войне в США с пояснениями что из-за чего и как оно вообще, то фильм откровенно разочарует. Он не о том. А вот если рассматривать фильм как рассказ о том, как молодая девушка, жаждущая славы, превращается в матерого и циничного фронтового фотографа, вот тогда да, фильм оправдывает себя.

Границы безумия (Upon Entry, 2022). Во-первых, это никакой не триллер, это разговорная драма, в которой все держится на диалогах и, в принципе, неплохой игре актеров. Во-вторых, следить за происходящим было интересно, но вот финал разочаровал. Как по мне, не смогли авторы сделать настоящую кульминацию.

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

Сериалы

Шугар (Sugar, первый сезон, 2024). В принципе норм (хотя и здесь уместна обычная придирка к сериалам -- общий хронометраж можно было бы запросто уменьшить на одну-две серии). Но есть одно большое но: перед просмотром нельзя читать какие-либо описания или подробные отзывы на этот сериал. Иначе вы заранее узнаете один из ключевых твистов и это украдет у вас часть впечатлений.

Магазин для киллеров (Killeodeului syopingmol, первый сезон, 2024). Ну такое себе. Посмотреть можно. Но слишком уж много маразма и "роялей в кустах".

Не смог досмотреть

Я не киллер (Hit Man, 2023). Хватило терпеть дебилизм происходящего минут на 20, потом не выдержал. Ну или это кино на совсем уж подростковую аудиторию.

Онегин (2024). Не смог. Просто не смог осилить больше получаса, настолько сильно было желание обосрать происходящее в кадре.

Не для слабонервных (Trigger Warning, 2024). Редкая халтура. Мало того, что выстрелы из автоматов нарисованы на компьютере, так даже поленились нарисовать гильзы, которые при стрельбе из автомата должны были бы вылетать. Ну и окончательно добила "рукопашка" в исполнении Джессики Альбы.

Фильм вне категории

Фуриоса: Хроники Безумного Макса (Furiosa: A Mad Max Saga, 2024). Очень и очень двойственные чувства. С одной стороны, мне понравилась рассказанная история. Следить за происходящим было интересно. Да и претензий к актерской игре у меня нет. Так что как история из "вселенной Безумного Макса" очень даже OK. Но вот визуальная составляющая настолько халтурная на фоне "Дороги ярости", что просто караул. В общем, как по мне, в этом фильме был бы смысл только если бы по картинке он был бы такой же, как и "Дорога ярости". Однако, не получилось :(((

пятница, 28 июня 2024 г.

[prog.c++] Пример того, что могут творить оптимизирующие C++ компиляторы

В догонку к предыдущему посту про скорость самодельного UTF-8 валидатора. Захотелось добавить в это же сравнение и is_utf8 на базе SIMD.

Задействовать is_utf8 несложно, пишется очередная check_validity_with_*:

bool
check_validity_with_is_utf8_simd(std::string_view str)
{
   return is_utf8( str.data(), str.size() );
}

И все.

Но не совсем, т.к. эта новая check_validity только возвращает true/false, тогда как старые реализации еще и суммировали извлеченные code-point-ы:

bool
check_validity_with_restinio(std::string_view str, std::uint32_t & out)
{
   restinio::utils::utf8_checker_t checker;
   forconst auto ch : str )
   {
      if( checker.process_byte( ch ) )
      {
         if( checker.finalized() )
            out += checker.current_symbol();
      }
      else
         return false;
   }

   return true;
}

Т.е. делали лишнюю работу. А раз работа лишняя, то от нее хорошо было бы избавиться:

bool
check_validity_with_restinio(std::string_view str)
{
   restinio::utils::utf8_checker_t checker;
   forconst auto ch : str )
   {
      if( !checker.process_byte( static_cast<unsigned char>(ch) ) )
      {
         return false;
      }
   }

   return true;
}

OK, сделано. Можно запускать бенчмарк и...

И внезапно я вижу какие-то нереальные цифры:

***     restinio: 8us ***
***  decode_2009: 12us ***
***  decode_2010: 11us ***
*** simd_is_utf8: 49176us ***

Это GCC-13.2 под Windows на i7-8550u, ключи компиляции:

g++ -O2 -std=c++20 -o utf8_checker_speed-gcc13.exe *.cpp

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

Оказалось, что компилятор GCC-13 настолько продвинут, что смог обнаружить отсутствие побочных эффектов в вызове обновленных версий check_validity_with_restinio, check_validity_with_decode_2009, check_validity_with_decode_2010. И ведь действительно, побочных эффектов там нет: на вход подаются одни и те же данные, на основе одних и тех же данных выполняются одни и те же вычисления. Соответственно, и результат вычислений всегда будет один и тот же.

Ну а раз результат всегда один и тот же, то нет смысла вызывать функции check_validity_with_restinio 100k раз, достаточно всего одного раза. Что GCC и сделал.

Отсюда и такие маленькие цифры -- это замер для всего одного вызова check_validity_with_*. А не для 100K вызовов, как задумывалось.

Тогда как в случае с is_utf8 компилятор не смог сделать выводов об отсутствии побочных эффектов (полагаю потому, что сама is_utf8 находилась в другой единице трансляции) и вызов check_validity_with_is_utf8_simd честно выполнялся 100K раз.

Чтобы понять что происходит пришлось заглянуть в ассемблерный выхлоп компилятора, чего я уже не делал лет сто, если не сто пятьдесят ;)

Еще прикольнее то, что GCC-11 не разобрался с отсутствием побочных эффектов у check_validity_with_restinio и честно вызывал ее 100k раз, тогда как вызовы check_validity_with_decode_2009 и check_validity_with_decode_2010 успешно "заоптимизировал". А вот GCC-13 смог справиться даже с utf8_checker_t из RESTinio. Что для меня выглядит ну совсем уже фантастикой.

Нужно сказать, что только GCC смог в такую крутую "оптимизацию". Ни с VC++, ни с clang ничего подобного не было.

PS. Если кому-то интересно, то вот результаты GCC-13.2 когда заставляешь его делать все 100k вызовов:

***     restinio: 535279us ***
***  decode_2009: 1197288us ***
***  decode_2010: 1137498us ***
*** simd_is_utf8: 53430us ***

вторник, 25 июня 2024 г.

[prog.c++] Любопытное на тему производительности самодельного проверяльщика UTF-8

Довелось недавно столкнуться с задачей проверки корректности UTF-8 представления. И в рамках этой задачи вышел вот на это замечательное описание с примерами двух реализаций: Flexible and Economical UTF-8 Decoder.

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

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

Но прежде чем сделать это попробовал провести простейшие сравнения производительности. И вот тут-то меня ждал сюрприз...

На основном рабочем Windows-ноутбуке с i7-8550U и VisualStudio 2022 (17.10.3) примитивный бенчмарк показывает следующие результаты:

***    restinio: 1240136us ***
*** decode_2009: 1784796us ***
*** decode_2010: 1774765us ***

Компиляция выполнялась так: cl -EHsc -O2 -DNDEBUG -utf-8 -std:c++20

На этом же Windows-ноутбуке под GCC-13.2.0 (из MinGW-w64) получаются следующие числа:

***    restinio: 435519us ***
*** decode_2009: 977052us ***
*** decode_2010: 566962us ***

Компиляция выполнялась так: g++ -O2 -std=c++20

На резервном Linux-ноутбуке с i7-6600U и GCC-13.1 этот же бенчмарк дает следующие числа:

***    restinio: 915891us ***  
*** decode_2009: 873742us ***  
*** decode_2010: 809853us ***

Но еще интереснее оказывается с GCC-11 на том же Linux-ноутбуке:

***    restinio: 941621us ***  
*** decode_2009: 1857220us ***  
*** decode_2010: 2047872us ***

Т.е., похоже, в GCC-13 оптимизатор серьезно прокачали, отсюда и гораздо лучшие результаты для решений от 2009-го и 2010-го годов под GCC-13.

Но намного больше пищи для размышлений дал clang-18:

***    restinio: 2108439us ***  
*** decode_2009: 1775339us ***  
*** decode_2010: 2012727us ***

Т.е. оптимизатор в clang-е с решениями 2009-го и 2010-го годов справился на уровне GCC-11, но вот наш код из RESTinio он настолько же сильно, как GCC-13, оптимизировать не смог.

Ну и для полноты картины результаты clang-16 с того же Linux-ноутбука:

***    restinio: 2379565us ***  
*** decode_2009: 3222073us ***  
*** decode_2010: 1839321us ***

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

Меня удивило другое: насколько разные результаты можно получить на одной и той же платформе с разными версиями одного и того же компилятора (не говоря уже о разных компиляторах).

Если взять специфику наших открытых библиотек, которые распространяются в исходниках, а затем компилируются на неизвестно каких платформах неизвестно какими компиляторами, то насколько уместно заниматься низкоуровневыми оптимизациями? Типа отшлифуешь все до последней микросекунды на Windows с VC++, а на Linux-е и 11-ом GCC, напротив, получишь просадку производительности.

PS. Я понимаю, что это негодный бенчмарк. Всего один набор тестовых данных. Весь код в одном файле, что не есть хорошо, если разнести функции по разным .cpp-файлам результаты могут отличаться, например, когда каждая функция декодирования помещается в отдельный C++ файл, то результы с GCC-13 под Linux-ом на i7-6600U меняются в пользу реализации от RESTinio:

***      restinio: 612732us ***
***   decode_2010: 820765us ***  
***   decode_2009: 855889us ***  

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

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

[prog] Один из признаков того, что с вашим кодом не все в порядке

Очень простой маркер трансформации в говнокод: закомментированные куски без пояснения причин почему эти куски были закомментированы и до какого времени они должны в таком виде оставаться.

Т.е. если вы видите в кодовой базе что-то вроде:

data_manager::data_manager(
  data_set_id id,
  raw_data_storage_shptr raw_data_storage,
  access_manager_shptr access_manager,
  modification_mode mode,
  logger log)
  : base_type{ id,
      std::move(raw_data_storage),
//     std::move(access_manager)
//     mode
    }
{
//  _id = id;
//  _storage = std::move(raw_data_storage);
//  _access_manager = std::move(access_manager);
  setup_access_manager(std::move(access_manager));
  setup_mode(mode);
  setup_logger(std::move(log));
}

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

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

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

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

Например:

data_manager::data_manager(
  data_set_id id,
  raw_data_storage_shptr raw_data_storage,
  access_manager_shptr access_manager,
  modification_mode mode,
  logger log)
  : base_type{ id,
      std::move(raw_data_storage),
//FIXME(eao197): access_manager и mode должны были бы передаваться
//в base_type, но там временно пришлось убрать такой конструктор.
//Нужно вернуться к передаче access_manager и mode в конструктор
//базового класса после того, как base_type будет отрефакторен.
//     std::move(access_manager)
//     mode
    }
{
  //FIXME(eao197): установка access_manager и mode должна
  //быть со временем перенесена в конструктор base_type.
  setup_access_manager(std::move(access_manager));
  setup_mode(mode);

  setup_logger(std::move(log));
}

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

воскресенье, 16 июня 2024 г.

[prog.java] Листая старенький айпад или как же похорошела Java за последние 14 лет ;)

Довелось тут давеча вспомнить когда в последний раз программировал на Java. Почему-то думал, что было это в 2012-ом, а оказалось, что в 2010-ом. Интересно сейчас, спустя 14 лет, перечитывать собственные старые впечатления. Особенно вот эти соображения о том, чего лично мне тогда не хватало в Java. И тем забавнее обнаружить, что часть из описанного мной тогда, в современной Java уже есть: это и автоматический вывод типов переменных, и лямбда функции, и try-with-resources.

Как же похорошела Java за эти годы! ;)

Только вот желания программировать на Java как не было, так и нет :)))

PS. Да и с кроссплатформенностью у .NET и C# стало куда как лучше.

вторник, 4 июня 2024 г.

[prog.c++] Полагаю, что не нужно использовать bool-параметры в функциях и методах. Ну вот вообще не нужно.

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

do_something(target, true, false, true, logger);

Глядя на такой код более-менее понятно с первого взгляда что означают target и logger. А вот какой смысл несут true, false и еще раз true -- без заглядывания в документацию (если вам повезло и таковая есть вообще) или в реализацию do_something не скажешь.

Рекомендация, кстати говоря, здравая. Но, как по мне, слишком специализированная. Я воспринял ее в более общем виде: нужно избегать идущих подряд аргументов одного типа. Не важно bool это, int, double или string. Когда видишь что-то вроде:

prepare_data(data, 0, 0, 42, 122);

то без плотного знакомства с prepare_data все равно не обойтись.

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

prepare_data(data, default_x, defaut_y, default_w, default_h);

то все равно некоторые проблемы остаются. Скажем, компилятор не ударит вам по рукам, если вы ошиблись в порядке следования аргументов одного типа. Возможно, правильно было бы писать так:

prepare_data(data, default_x, defaut_w, default_y, default_h);

Так что если у вас есть возможность пользоваться каким-то из вариантов strong typedef, то лучше им таки пользоваться. Отличная защита от опечаток. Да и в чужой код легче погружаться, когда там в прототипах функций вместо int-ов используются x_coord, y_coord, width и height.

Но вернемся к аргументам типа bool.

За последний год пришел к выводу, что bool в качестве типа параметра -- это вообще ни разу не хорошо.

И вовсе не по тем причинам, которые когда-то описал Мартин Фаулер. А тупо потому, что читать чужой код, в котором раскиданы совершенно неинформативные true и false -- это то еще удовольствие:

auto it = data_cache.get(item_key, true);
...
it = data_cache.validate(it, false);

Когда видишь такой код впервые, то сразу спотыкаешься на true и false, пытаясь выяснить что они означают вообще.

Совсем другое дело, когда используются enum classes и именованные константы:

auto it = data_cache.get(item_key, cache_item_creation::create_if_missed);
...
it = data_cache.validate(it, cache_validation::dont_update_timestamp);

Так что с годами пришел к выводу, что в современном C++ c enum-class bool-аргументы не должны использоваться вообще.


PS. По поводу упомянутого выше Мартина Фаулера. Ну не убеждают меня его доводы. Хотя, если вы не будете использовать bool-параметры под влиянием аргументов Фаулера, то я возражать не буду ;)

суббота, 1 июня 2024 г.

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

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

Фильмы

Артур, ты король (Arthur the King, 2024). Хорошее, доброе, семейное кино. К некоторым местам я бы сильно доколупался бы. Но именно как кино для семейного просмотра, как по мне, так отлично.

Каскадёры (The Fall Guy, 2024). Смотрибельно, но... Во-первых, фильм, как мне показалось, рассчитан на малолетнюю и непритязательную аудиторию. Людям постарше тупо не интересно следить за происходящим. Во-вторых, главным героям, судя по поведению, должно быть лет по 25, а играют их сорокалетние актеры. Это вызывает неслабый диссонанс. В-третьих, гораздо интереснее оказалось смотреть сцены во время финальных титров о том, как проходили съемки трюков.

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

Атлас (Atlas, 2024). Очень предсказуемый и детский фильм. Но красочно снят. Так что на фоне того, что красиво сделанной фантастики в последнее время очень мало, то потраченного времени не жаль. Но далеко не шедевр.

Министерство неджентльменских дел (The Ministry of Ungentlemanly Warfare, 2024). Красочный фантастический комикс для детей младшего школьного возраста. Людям старше 12-13 лет можно не смотреть чтобы не разбить себе лицо фейспалмами.

Сорвать банк (Cash Out, 2024). Очень и очень слабо, как по актерской игре, так и по визуальной составляющей. А уж сценарий так просто днищенское дно.

Сериалы

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

Оффлайн (первый и второй сезоны, 2022-2024). Первый сезон, как по мне, так просто отличный, очень легко смотрится. А вот второй -- это какой-то бред укуренного наркомана. Так что моя рекомендация -- посмотреть только первый сезон и не обращать внимания на продолжение.

Амстердам: Город грехов (Baantjer het Begin, первый сезон, 2019). Начало было многообещающим, но начиная с середины сериал скатился в откровенную посредственность. Не буду ругать, но и рекомендовать не могу.

Фильм вне категории

Большая гонка. Ауди против Лянчи (Race for Glory: Audi vs. Lancia, 2024). Странное кино. По нынешним меркам откровенно слабое. Но веет от него какой-то аналоговой теплой ламповостью 1980-х. Настолько, что вспомнилось старое-старое кино 6000 километров страха от 1978-го года, увиденное в далеком детстве. В результате нашел "6000 километров..." на YouTube, пересмотрел, понастольгировал. Мне кажется, что "6000 километров..." намного лучше. Но есть впечатление, что "Ауди против Лянчи" специально делали именно таким, аналоговым и ламповым, под старые фильмы 1980-х о раллийных гонках. Так что не возьмусь давать какую-то оценку.

четверг, 30 мая 2024 г.

[prog.c++] Грустные впечатления от p3086

Недавно в очередной раз наткнулся на библиотеку proxy от Microsoft. Которая разработана в качестве поддержки предложения p3086. Попробовал почитать этот пропозал (2-я ревизия на тот момент). Спектр эмоций оказался широким -- от нехилого пригорания по началу до тихой грусти в итоге. Попытаюсь рассказать почему.

Началось все буквально с первых страниц. Вот на этом фрагменте у меня полыхнуло:

For decades, object-based virtual table has been a de facto implementation of runtime polymorphism in many (compiled) programming languages including C++. There are many drawbacks in this mechanism, including life management (because each object may have different size and ownership), reflection (because it is hard to balance between usability and memory allocation) and intrusiveness. To workaround these drawbacks, some languages like Java or C# choose to sacrifice performance by introducing GC to facilitate lifetime management, and JIT-compile the source code at runtime to generate full metadata.

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

facepalm.jpg

Ну как бы это помягче сказать.

среда, 22 мая 2024 г.

[prog.c++.fantasy] Даешь по два стандарта в год!

Отдельная боль для меня в последние годы -- это возврат C++ к ситуации, которая была с первым стандартом в конце 1990-х: стандарт вышел, а компиляторов, которые бы его поддерживали, пришлось ждать несколько лет. А пока этого не случилось приходилось оглядываться на то, что есть в конкретном компиляторе.

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

Однако, C++20 вернул нас в старые и недобрые времена. Уже середина 2024-го года, а полностью и нормально C++20 вроде как нигде и не реализован.

Что в этом плохого лично для меня?

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

Это все время. Чем дольше приходится ждать поддержки очередного стандарта, тем больше уходит этого самого времени 🙁

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

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

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

Не, реально.

Вот есть N предложений в работе. Какая-то часть из уже готова к включению в стандарт и просто ждет, пока же придет время фиксации этого стандарта. Так зачем ждать год-полтора-два, если уже есть готовые предложения? Давайте фиксировать по два стандарта в год. Например, весной -- C++24.1, осенью -- C++24.2. На следующий год весной будет C++25.1, а затем, осенью 2025-го, C++25.2 и т.д.

Как по мне, так хуже не станет.

Большие фичи, вроде модулей из C++20, могут (и будут) реализовываться годами. В 2024-ом году для меня нет разницы не реализованы ли модули из C++20 или же из C++23.2. Все равно же не реализованы.

Зато какая-нибудь мелкая фича, типа std::start_lifetime_as могла бы стать доступной для разработчиков в гипотетическом C++22.1, а не в С++23. Или вот в C++26 обещают добавить возможность обращаться к элементам parameter pack прямо по индексу. Так зачем ждать C++26, если можно включить ее в C++24.2?

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

Да, комитет по развитию C++ нужен. Спецификации языка, выпускаемые этим комитетом, нужны.

Но вот нужен ли на этих самых спецификациях штамп "ISO"? Сильно сомневаюсь. Возможно, в 1990-е развитие в рамках ISO имело смысл. Сейчас же его сложно разглядеть. А посему можно и задаться вопросом: а стоит ли сейчас цепляться за существующую модель стандартизации C++ или же выгоднее ее пересмотреть?

понедельник, 20 мая 2024 г.

[prog.c++] Первые краткие впечатления от C++20

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

spaceship operator. "Дайте два!" После того, как попробуешь, просто не хочется возвращаться на C++17.

designated initializers. Отличная штука для простых структур с двумя-тремя полями.

std::span "изкаропки". Очень удобно.

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

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

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

class class_with_complex_logic {
  concept MyRequirement = ...;

  template<MyRequirement Param>
  void do_something(Param && param) {...}

  template<MyRequirement Param>
  void do_something_else(Param && param) {...}
  ...
};

суббота, 11 мая 2024 г.

[prog.c++] Из непонятого: как же лучше погружать в современный C++ новых людей?

У меня недавно закончился небольшой контракт на проведение для молодых программистов чего-то вроде "курса молодого бойца" по C++. Что заставило в очередной раз задуматься на тему "а не стал ли C++ настольно монстрообразным, что обучить новичка практически невозможно?"

Но это сильно глобальный вопрос, я даже не знаю как к нему подойти. Радует лишь то, что сам я C++ изучаю года с 1991-го, когда это был, мягко говоря, совсем другой язык. Гораздо более простой, последовательный и логичный. И мне повезло, что на эту небольшую базу затем инкрементально ложились новые возможности: пространства имен, исключения, шаблоны, STL и т.д., и т.п. Т.е. сам я учил C++ по мере того, как в него добавлялись новые фичи. И поскольку добавлялись они раньше не в таком количестве и не с такой скоростью, то поспевать за ростом сложности C++ где-то до 17-го стандарта еще удавалось. Однако, на C++20 это уже сломалось даже для меня :(

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

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

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

Как по мне, Си и C++ уже очень и очень давно совершенно разные языки. Да, в C++ есть изрядное подмножество чистого Си, но все-таки идеология C++ другая и к таким вещам, как ссылки, классы, деструкторы, нужно привыкать сразу. Чем меньше приемов из чистого Си, тем лучше.

Поэтому вроде как есть смысл новичков сразу учить использовать то хорошее, что есть в C++. Например, std::string для строк вместо char*, std::string_view вместо const char*, std::vector и std::array вместо Си-шных массивов, std::find_if вместо голых циклов и вот это вот все.

Но тут есть серьезная засада, особенно в случаях, когда у новичков за плечами уже есть опыт работы с языками со сборкой мусора (будь то Python или Java, не суть важно). По моим впечатлениям у тех, кто изучает C++ сейчас, есть проблемы с пониманием разницы между values и references. Грубо говоря, люди пишут:

void f(std::string param) {...}

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

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

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

Рефлексируя на эту тему я пока придерживаюсь мнения, что виной тому как раз использование готовых "высокоуровневых" возможностей STL. Те же самые std::string и std::vector освобождают программиста от изрядного геморроя, но не дают этому самому программисту понимания того, как же это все работает "под капотом". А без такого понимания сложно программировать на C++ эффективно.

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

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

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

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

Во-вторых, по моему субъективному мнению, написание библиотек классов (пусть даже в такой библиотеке будет всего лишь string, vector и hash_map) требует несколько иных навыков, нежели написание прикладного кода. Да, возможно это тараканы в моей голове, но я убежден, что библиотеко-писатели и прикладники -- это разные специалисты. Бывают, конечно, и те, кто одинаково хорош и в том, и в другом, но это такое же частое явление, как и хорошие программисты, вырастающие в хороших менеджеров. В общем, начиная с реализации собственных string и vector можно не получить должного эффекта, если обучаемый больше склонен к решению прикладных проблем, чем к написанию библиотек.

В-третьих, этот подход как раз таки очень близок к подходу, когда мы сперва учим людей чистому Си, а уже затем переходим к использованию высокоуровневых возможностей C++. Близок, не не тождественен. Тем не менее, если молодой разработчик привыкает писать относительно низкоуровневый код с ручными new/delete, alignof/alignas и пр. заморочками, то есть опасность, что он и продолжит в том же духе. Тут людей сразу пытаешься учить пользоваться std::unique_ptr и std::make_unique, а они все равно норовят использовать голые владеющие указатели с new/delete... Что уж говорить о тех, кого специально с самого начала ограждают от std::unique_ptr, std::optional, std::variant, std::vector и т.д.

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

В завершение еще раз поделюсь своими тягостными впечатлениями о том, что C++ на мой взгляд, стал слишком уж большим и сложным для того, чтобы его мог изучить и освоить человек "со стороны". Речь не о старпёрах, вроде меня, кто за 30 лет в программизме имел возможность осваивать фичи "современного C++" по мере их появления. А о тех, кто про C++ ничего не знал, но должен изучить за относительно небольшое время. Как таким новичкам преподавать тот же С++20? Вот это вопрос.

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

четверг, 2 мая 2024 г.

[prog.c++] Одно из недооцененных мной качеств C++

Есть в C++ одно качество, на которое я сам начал обращать внимание относительно недавно, года три или четыре назад. А вот поговорить об этом захотелось только сейчас, после выхода большой статьи "Leaving Rust gamedev after 3 years" (ее перевод уже начали делать и на Хабре -- вот первая часть).

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

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

Читая эту "претензию" к Rust-у вспомнил про то самое качество C++ о котором и пойдет сегодня речь.

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

Да, да. Речь именно о том, что на C++ любой "недоучка" может написать работающий говнокод. Ключевое здесь "работающий", а "говнокод" -- это так, функция от времени ;)

И, что еще интереснее, даже работающий с приемлемой скоростью.

Т.е. неопытный C++ник из говна и палок может получить нужное ему решение.

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

Но здесь и сейчас он будет работать.

И, что удивительно, на ранних этапах жизненного цикла нового софта это все, что требуется.

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

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

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

Выше я не зря взял термин "недоучка" в кавычки. Иногда это студенты, которые слишком рано, не имея практического опыта, попали "под крыло" к специалистам в какой-то узкой прикладной нише. Иногда это люди, которые уже умеют программировать и, зачастую, делают это очень хорошо. Но не на C++, а на Python-е или VisualBasic-е, к примеру. Да и вообще в своей предметной области съели не одну собаку. И, что самое важное, они знают что нужно клиентам и как это клиентам продать.

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

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

Так-то я привык к работе в условиях, когда качеству уделяется серьезное внимание, и думал, что подход "фигаг-фигак-и-в-продакшен" за последние 15-20 лет из C++ полностью ушел в Java, Python и Go. Просто в силу того, что ниша C++ все эти годы скукоживается и C++, к счастью, остается лишь там, где в этом еще есть смысл.

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

Почему не ведет к фатальным последствиям для меня пока еще загадка. Могу предположить, что здесь здорово помогают современные средства разработки с крутыми отладчиками, анализаторами и санитайзерами. Ну и стандартная библиотека C++, хоть и остается куцей, но хотя бы std::vector и std::string уже есть везде, не нужно свое колхозить, как было в 1990-х.

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


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

Но если над кодовой базой должно работать несколько десятков человек с разной квалификацией, то C++ плохой выбор (жирное ИМХО).

среда, 1 мая 2024 г.

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

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

Фильмы

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

Хитмен. Последнее дело (Knox Goes Away, 2023). Отличная развязка. Но чтобы ее дождаться придется вытерпеть полтора часа скучной тягомотины.

Манкимэн (Monkey Man, 2024). Ну что тут сказать? Можно вывезти индуса в Голливуд, но вывести Болливуд из индуса невозможно. Как по мне, так даже попытки сделать экшОн в духе "Джона Уика" не помогают.

Сериалы

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

Fallout (первый сезон, 2024). В игры Fallout никогда не играл и даже ничего про них не слышал, кроме того, что такие игры есть в принципе. А вот экранизацию было интересно смотреть даже несмотря на отсутствие каких-либо знаний о фантазийном мире Fallout-а. Отличный получился треш на тему выживания после глобальной ядерной войны. Но! Кино явно для любителей подобного треша.

Банда «ЗИГ ЗАГ» (первый сезон, 2023). Динамично. Нет ни грамма сериальной затянутости. Но столько клюквы развешено, что как-то не по себе местами становится.

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

воскресенье, 28 апреля 2024 г.

[life.photo] В первые за долгое, долгое время сделал несколько кадров на полноценную камеру

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

Хочется надеятся, что возможностей и желания прогуляться с фотокамерой будет больше, чем в последние 3-4 года.

четверг, 25 апреля 2024 г.

[prog;work;wow] Марко Арена завершил свою серию статей про SObjectizer

Марко Арена сегодня завершил свою серию статей "SObjectizer Tales", начатую в октябре прошлого года. Полный список статей из этой серии я приведу ниже.

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

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

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

Как по мне, так Марко написал целую книгу. Что по объему, что по глубине и качеству материала.

И, что особенно радует, так это то, что написано все это не кем-то из SObjectizer Team, а пользователем SObjectizer-а. Скажи мне об этом кто-то еще года два-три назад, я бы счел подобное ненаучной фантастикой. А теперь это реальность.

Более того, я бы даже назвал выход серии "SObjectizer Tales" целой вехой в истории развития SObjectizer-а. Важной и значимой лично для меня.

Так что, да, я шокирован. В хорошем смысле этого слова.


Вот как в итоге выглядит вся серия.


PS. Что доставляет отдельно, так это слоган, который Марко выбрал для своей серии: Concurrent C++, made simple. Таки да, для этого все когда-то и затевалось. Но я бы насколько лаконично и емко выразить бы не смог.

понедельник, 22 апреля 2024 г.

[prog.c++] Вредных советов пост: пара-тройка способов усложнить жизнь тем, кто будет сопровождать код после вас

Хочу поделиться многолетним опытом. Работает на 100%, а иногда и на все 146%. Так смело можете брать на вооружение, если решили конкретно поднасрать своим коллегам.

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

Поверьте, настоящие программисты (тм) всегда будут точно знать, что означают it->first или std::get<3>(*it).

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

Не обращайте на них внимания. Это же склеротики, которые не могут удержать в памяти даже два простых названия -- first и second, хотя что может быть проще? Ну и наверняка им платят за строчки кода, а не за решение проблем. Вот они и фигачат по 100500 строк там, где можно обойтись одним std::pair-ом.

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

Если у нас есть строковое имя пользователя и строковый же пароль в виде открытого текста, то достаточно простого std::string.

Вводить какие-то новые типы UserName и PlainTextPassword? Ради чего? Ради того, чтобы случайно не пихнуть пароль туда, где ожидается имя пользователя?

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

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

Так что никаких strong typedef-ов. Забудьте как страшный сон.

Ну и в качестве бонуса: вам не нужны ни using, ни typedef. Если у вас есть map, значением которого будет vector из queue, то вот прямо так и нужно записывать. Никаких вспомогательных using-ов и typedef-ов!

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

void process_appropriate_items(
      const std::vector<
            std::pair<
                  std::pair<intint>,
                  std::tuple<std::string, std::string, std::string, std::string> > > & what)
{
   for(const auto & p : what)
      if(p.first.second > 0)
         process(std::get<3>(p.second));
}

Зачем выдумывать что-то еще? Неужели вам не понятно что означает p.first.second и std::get<3>(p.second)? Да ну, не может такого быть!


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

среда, 17 апреля 2024 г.

[life;work;business] 10 лет с начала нового этапа в профессиональной жизни

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

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

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

Теперь знаю 😉

Теперь и сам могу упрекнуть кого хошь 😆

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

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

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

Советовать кому-то пойти по этому же пути не буду.

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

Так что могу лишь перефразировать классика: открывать свое дело нужно не тогда, когда ты можешь это сделать, а тогда когда не можешь не сделать.

Вопрос лишь в том, чтобы отличить одно от другого.

Ну а я продолжу свой путь дальше. Посмотрим, что будет в последующие десятилетие. Как показывают последние 4-5 лет, случится может такое, что и нафантазировать трудно. Поэтому не исключаю и сценария, когда буду обычным программистом с минимумом ответственности, работающим с 9 до 17 над тасками из Jira, все мысли которого посвящены выращиванию капусты на домашнем огороде. Who knows, who knows... 🤔

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

ЗЫ. Что-то много смайликов в посте. Не специально, просто "...Это нужно для того, чтобы человечество весело расставалось со своим прошлым" (с).

ЗЗЫ. Тогдашний "Интервэйл" все еще вспоминается с большой теплотой. Действительно, чуть ли не лучшие годы и все такое... Но то тогдашний. Вроде как от тогдашнего сейчас мало что осталось.


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

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

понедельник, 15 апреля 2024 г.

[work] Открыт для сотрудничества в качестве C++ разработчика

В виде (суб)контракта с нашей компанией СтифСтрим.

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

Самостоятельно погружаюсь в проблему, нахожу решение, кодирую, тестирую, документирую. Если нужно обучаю. Если нужно сопровождаю и поддерживаю. Если нужно выступаю в качестве евангелиста (см. список публикаций на Хабре).

Работаю не быстро, но качественно, беру недорого.

Оценить мой уровень можно, например, про проекту aragata, реализованному мной практически в одиночку. Код можно увидеть на GitHub-е, на Хабре есть две статьи о том, что это и как работает: вводная статья и описание сделанных по результатам нагрузочных испытаний оптимизаций + вот этот пост.

В качестве дополнительных примеров: timertt (+ документация), so5extra (+ документация) -- эти проекты так же написанные мной самостоятельно.

Связаться со мной можно через eao197 на gmail тчк com. Если кому-то интересен профиль на LinkedIn, то вот.


Это сообщение повисит какое-то время вверху. Потом будет видно, имеет ли смысл пытаться дальше оставаться в C++.

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

В течении последнего года, может быть чуть меньше, регулярно стал натыкаться в разных кодовых базах на паттерны вроде вот такого (внимание на тело цикла for):

bool does_contain_apropriate_item(
   const item_container & items,
   const search_criteria & search_params)
{
   for(const auto & i : items) {
      if(!does_meet_coditions(i, search_params)) {
         continue;
      }

      return true;
   }

   return false;
}

Зачем нужен continue в цикле и почему нельзя сразу написать:

bool does_contain_apropriate_item(
   const item_container & items,
   const search_criteria & search_params)
{
   for(const auto & i : items) {
      if(does_meet_coditions(i, search_params))
         return true;
   }

   return false;
}

Большая и неразрешимая для меня загадка.

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

PS. Почему не используется в таких случаях std::find_if -- это отдельный вопрос. Местами не такой простой, как может показаться. Тем более, что я привел не реальный фрагмент кода, а общую схему того, что вижу в последние месяцы регулярно. Детали же часто сильно отличаются, иногда еще нужен и индекс найденного элемента, так что на практике std::find_if не всегда такая уж удобная замена.

вторник, 2 апреля 2024 г.

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

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

Фильмы

Холоп 2 (2023). Вполне на уровне первого фильма. Но, как раз это немного и разочаровывает: как все предсказуемо, хотелось бы, чтобы авторы чем-то удивили. А удивили разве что масштабной батальной сценой в финале. Вот это было здорово.

Дом у дороги (Road House, 2024). Если раньше смотрели "Дом у дороги" с Патриком Суэйзи от 1989-го, то современный ремейк будет "немного предсказуемым". Но глянуть его можно хотя бы ради красочно поставленных рукопашных сцен.

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

Ангел мести (Fatum, 2023). Посредственно, но смотрибельно. Хотя и далеко не шедевр.

Анатомия падения (Anatomie d'une chute, 2023). Если не жалко потратить 2.5 часа своего времени на то, чтобы узнать за что же именно был вручен "Оскар", то можно и глянуть. Но меня фильм не зацепил: ни история сама по себе, ни то, как она была рассказана, ни игра актеров. А уж работа оператора как и вообще раздражала, как будто телеспектакль с советского ТВ посмотрел.

Молчание ангелов (Englemageren, 2023). Пока смотришь, то кажется, что бюджетно, но более-менее смотрибельно. Но вот финал ошарашивает таким маразмом, что становится жалко потраченного на просмотр времени.

Три мушкетера: Миледи (Les Trois Mousquetaires: Milady, 2023). Как по мне, так редкостная дрянь. Категорически не советую тратить на это "кино" свое время.

Сериалы

Медиатор (третьий сезон, 2024). Если первые два сезона понравились, то можно смело смотреть и третий. Мне зашло. На фоне других современных российских (да и не только) сериалов, так прям отдохновение.

Джентльмены (The Gentlemen, первый сезон, 2024). Пара первых серий и пара последних, как по мне, так отличные. В середине ну такое себе, можно было бы и подсократить хронометраж. Но в целом посмотрел с удовольствием.

Джетт (Jett, 2019). В целом неплохо и бодренько. Но общее впечатление портит, во-первых, то, что явно был сделан намек на следующий сезон, которого не состоялась. Так что история не была завершена и это раздражает. Во-вторых, хоть Карла Гуджина и выглядит совершенно замечательно для своих лет, но все-таки заметно, что она лет на 10 постарше своей героини.

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

Halo (второй сезон, 2024). Смотреть можно разве что тем, кому понравился первый сезон. Мне первый сезон не то, чтобы понравился, но просто захотелось посмотреть что-то из жанра "боевой фантастики". Местами норм, местами скучно. Ну и везде какая-то бессмыслица происходит, как по мне :)

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

Не смог осилить

Костолом (Ruthless, 2023). Какая-то унылая и бюджетная попытка показать ещё одного "боевого пенсионера", в одиночку расправляющегося с кучей бандитов. Уж лучше пересмотреть первую часть "Заложницы".

Уцелевший (Warhorse One, 2023). С самого начала какой-то маразм + ну какой-то совсем уж ущербный уровень компьюетрной графики, так что я не смог выдержать и пятнадцати минут.

воскресенье, 31 марта 2024 г.

[prog.c++] Оказывается, для VC++ недостаточно ключа -std для того, чтобы получить актуальное значение __cplusplus

Если вы, как и я, думали, что указав компилятору ключ -std:c++20 вы автоматически получите корректное значение __cplusplus, то вы заблуждаетесь :(

Кроме ключа -std:c++20 нужно еще и ключ -Zc:__cplusplus указать. Цинк:

$ cat t.cpp
#include <iostream>

int main() {
        std::cout << __cplusplus << std::endl;
}

$ cl -EHsc -nologo -std:c++20 t.cpp
t.cpp

$ ./t.exe
199711

$ cl -EHsc -nologo -std:c++20 -Zc:__cplusplus t.cpp
t.cpp

$ ./t.exe
202002

Рецепт найден здесь.

Что тут остается сказать кроме "Вот уроды!"...

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

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

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

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

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

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

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

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

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

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

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

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

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