суббота, 20 декабря 2014 г.

[prog.c++] Механизм registered_delivery для сообщений в SObjectizer

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

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

пятница, 19 декабря 2014 г.

[prog.thoughts] Message-passing: чем примитивнее, тем лучше?

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

четверг, 18 декабря 2014 г.

[prog.thoughts] FiniteStateMachines vs Coroutines

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

Но, с другой стороны, уже лет двадцать как использую подход на основе конечных автоматов и получаю вполне себе нормальные результаты. Конечно же, никто не признает себя плохим программистом, поэтому и мне кажется, что в моих проектах все было нормально, а как оно на самом-то деле... Ряд LOR-овских экспертов твердо убежден, что программировать я не умею от слова совсем ;) Тем не менее, проекты выполнялись, программы работали, прибыль приносили. Посему далее считается, что конечные автоматы могут успешно использоваться в concurrent programming.

Поэтому-то и интересен вопрос: действительно ли FiniteStateMachines и Coroutines объективно имеют разные области применения? Или же я из-за старперства застрял на конечных автоматах и мне просто уже не хватает гибкости ума для того, чтобы оценить и перейти на использование более передового подхода на основе сопрограмм (хотя самим сопрограммам уже сто лет в обед, т.к. впервые о них заговорили в 1958 году).

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

среда, 17 декабря 2014 г.

[life.photo] Свершилось: многопиксельная среднеформатная беззеркалка

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

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

Как я понял, там совсем новая серия оптики (!), а вот цифровой задник используется обычный, PhaseOne-овский IQ. Соответственно, можно получить 50-ти, 60-ти или 80-мегапиксельную камеру.

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

[prog.memories] Помнится, обрабатывал когда-то большие объемы данных на Ruby...

Вот эта запись в FB навеяла воспоминания об одной из задачек, которую мы решали в "Интервэйле" сначала с помощью Ruby, а затем C++.

Суть была в том, что один из программных комплексов писал на диск множество "протокольных файлов", т.е. файлов, в которых фиксировались следы обработки транзакций. Вроде такого: начали фазу #1, получили результат фазы #1, начали фазу #2, получили результат фазы #2 и т.д. По мере накопления информации в протокольных файлах ее нужно было извлекать и записывать в большую историческую БД. А уже по содержимому БД затем строилась всяческая статистика и отчеты.

Где-то в 2005-м или 2006-м для решения задачи импорта протокольных файлов в историческую БД был использован язык Ruby. Что казалось разумным. Код короткий, не сложный, основное время тратится на парсинг текста из файла и операции с БД. Т.е. в основном должны были работать низкоуровневые процедуры, написанные на C (либо в дебрях работы с регулярными выражениями, либо внутри ODBC-драйверов), так что общая тормознутость Ruby препятствием не должна была быть.

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

Нужно сказать, что сам скрипт импорта работал по крайне примитивному алгоритму. И можно было бы получить заметный выигрыш за счет смены алгоритма. Но предварительные разбирательства с узкими местами показали, что огромное количество времени тратится внутри Ruby-библиотеки для работы с СУБД. Причем тормозит именно Ruby-новый код, который формирует обращения к ODBC-слою. Т.е. здесь тормоза Ruby показали себя во всей красе.

Соответственно, ребром стал совсем не праздный вопрос: а имеет ли смысл реализовывать на тормозном Ruby более изощренный алгоритм импорта, если часть выигрыша все равно будет съедена неповоротливостью Ruby-нового рантайма?

К этому добавилась еще одна проблемка -- динамическая типизация. Динамическая типизация очень хороша в маленьких скриптах, написанных на выброс. Но когда приложение живет и развивается годами, когда разные его куски переписывают/дописывают разные люди, когда в течении месяцев в работающий код никто вообще не заглядывает, то динамическая типизация начинает играть против разработчика. Слишком много времени уходит на то, чтобы восстановить детали работы того или иного куска кода. Особенно, когда там задействуются более-менее сложные структуры данных. В статически-типизированном языке довольно просто -- сразу видно, что вот здесь список из объектов, внутри которых словари, элементами которых являются мультимножества, ключом в которых вот это, а значением -- вектор вот таких структур. Тогда как в Ruby-коде такие вещи нужно как-то по-другом раскапывать. Даже при наличии хорошего кода и комментариев в нем.

В общем, году в 2010-м мы все это дело переписали на C++. Заодно и применив более хитрый алгоритм, в котором часть данных предварительно накапливалась и обрабатывалась в ОП, тем самым, существенно уменьшалось количество последующих запросов к СУБД. Здесь было довольно много работы в ОП, и мне даже сложно представить, насколько все это было бы медленнее в Ruby. В итоге, новая C++ная версия импорта оказалась, как минимум, на порядок быстрее предыдущей или даже более быстрой, но этого я уже не помню, склероз... :) Может бывшие коллеги меня поправят. (Upd. Очевидцы подсказали, что время обработки было снижено с двух десятков часов до десятка минут.)

Эта история стала для меня еще одним подтверждением того, что скриптовые языки и серьезные задачи -- это плохо совместимые вещи. Огромное достоинство программ на скриптовых языках для меня -- это возможность поправить что-то прямо на целевой машине. Со скомпилированным в бинарник C++ кодом так не получится, а вот в Ruby-коде учесть какую-то особенность целевой платформы прямо на месте -- запросто. Однако, как только появляется намек на то, что программа должна работать быстро и в течении длительного времени, то от скриптов и динамики лучше сразу уйти. Тем более, что современные мейнстримовые компилируемые языки (C++, Java, C#) уже обзаводятся конструкциями, позволяющими писать меньше кода, но не терять ни в читабельности, ни в скорости работы.

вторник, 16 декабря 2014 г.

[life.humour] Вчерашним падением RUB навеяло

Прошу прощения, что опять пишу о том, в чем не разбираюсь. Но, имхо, с таким курсом валют РФ смело может снять все запреты на поставку продукции, которые были введены в качестве ответа на западные санкции. Например, на поставку польских яблок. Смысла продавать их в РФ, пересчитав стоимость из USD в RUB не будет. Но и винить за это РФ не получится -- невидимая рука рынка, ёптыть.

Походу, правительству РФ нужно только приветствовать рост USD/EUR и всячески поддерживать эту тенденцию. Тогда за голову схватятся не только польские фермеры. Но вообще все, кто импортирует что-то свое в РФ, начиная от запчастей для авто и заканчивая сложной техникой и технологиями. Или живет за счет туристов из РФ...

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

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

[life.sport.darts] Мои личные впечатления от прошедшего Кубка Гомеля

Вчера мы провели первый настоящий городской турнир "Кубок Гомеля 2014". Разговоры о чем-то подобном велись на протяжении последних 4-х лет, как внутри неформального дартс-клуба "Интервэйл-Гомель", так и на официальном форуме БПФД, где время от времени всплывала тема "местечковых турниров". Но воплотить в жизнь мы смогли это только сейчас.