пятница, 17 апреля 2015 г.

[prog.sobjectizer] В версии 5.5.5 планируется реализация фильтров сообщений

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

Здесь описана кажущаяся реальной идея реализации фильтров сообщений. Если у кого-то будет желание обсудить или высказать свое мнение, то милости прошу (либо на SF.net, либо на GitHub, либо прямо здесь, в блоге). Любое мнение будет услышано и принято во внимание. Со своей стороны готов подробно рассказать что к чему и почему. А так же проработать альтернативные варианты.

PS. Планирую и впредь делать анонсы таких вот обсуждений. Короткие. Кому интересно, тот присоединится, кому нет -- просто пропустит.

[prog.management] Подпольные проекты как способ протягивания новинок в продакшен

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

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

Хорошим ответом на этот вопрос могут стать "подпольные проекты".

четверг, 16 апреля 2015 г.

[prog.dreams] Если бы SObjectizer-6 начали делать сейчас...

На самом деле, почему бы не пофантазировать? Пока что совместимость между версиями SO-5 важна, поэтому в серии 5.5.* нет серьезно ломающих что-то изменений. Но когда-нибудь груз совместимости окажется совсем уж неподъемным и вот тогда проще будет сделать SO-6, чем допиливать SO-5.5.1529... А тут уже и список готовый есть ;)

На SF.net создана соответствующая тема. Можно писать свои соображения там. Можно и здесь.

В общем, если у кого-то есть, что сказать, то не держите в себе, высказывайтесь :)

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

PS. На счет того, что SO-6 следует разрабатывать прямо на GitHub троллить не нужно :)

среда, 15 апреля 2015 г.

[prog] Паттерн Async Completion Token

Есть такой простой и удобный, в некоторых случаях, паттерн под названием Async Completion Token. Но так как он удобен только в некоторых случаях, то не всегда вовремя вспоминается. А жаль. Поскольку иногда он позволяет перейти от stateful-модели к stateless.

вторник, 14 апреля 2015 г.

[prog.management] Про подпольные проекты на примере из истории Apple Lisa

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

понедельник, 13 апреля 2015 г.

[prog.c++11] Чуть подробне про решение md5_bruteforce2 на SObjectizer

Под катом чуть более подробное описание решения задачи md5_bruteforce2 на SObjectizer.

[prog] md5_bruteforce2: продолжение флешмоба по новым правилам

Предыдущий флешмоб по поводу задачи md5_bruteforce показал, что в простом виде эта задача не очень показательна. Действительно, если проблема в том, чтобы подобрать пароль максимально быстро, то задача решается одним способом (тупо деление всего диапазона по количеству ядер, на каждом ядре простой цикл). Если же цель показать, как можно использовать возможности языка и/или библиотеки в области concurrent programming, то пример не очень выразителен, т.к. в нем мало взаимодействий между параллельно работающими сущностями.

Ув. тов.asfikon, инициатор первого флешмоба с простой реализацией md5_bruteforce, поддерживает список решений в своем посте eax.me/go-goroutines. Там можно найти решения исходной задачи на Go, D, Rust, Scala, Clojure, C++,...

Поэтому в процессе обсуждения результатов простого md5_bruteforce, возникла идея, что данную задачку можно сделать более привлекательной с точки зрения именно concurrency, а не parallel computing. В результате чего новая задача формулируется следующим образом (огромное спасибо ув.тов.swizard-у за первоначальную формулировку):

  • Программа представляет собой многопоточное приложение, с архитектурой: мастер + один или несколько воркеров.
  • Количество воркеров определяется на старте программы, и, обычно, равно количеству вычислительных ядер в машине.
  • Мастер вычитывает задания из stdin построчно и раздаёт их свободным воркерам. Пустые строки могут игнорироваться сразу и не восприниматься как задания. Чтение должно либо чередоваться с обработкой, либо вестись параллельно. Нельзя однократно прочитать содержимое stdin от начала до конца и лишь затем приступить к обработке прочитанного (т.к. программа должна иметь возможность работать в составе, например, конвейера в течении длительного периода и обрабатывать миллионы/сотни миллионов/миллиарды строк с stdin).
  • Задание -- это md5-сумма пароля и диапазон возможных значений пароля. И нижняя, и верхняя граница интервала входит в поиск (т.е. диапазон вида [lower,upper]).
  • Символы пароля и интервалов могут быть либо цифрами, либо строчными латинскими буквами.
  • Пример строки с заданием: fec91335051486b245d74cdb6042d4c0 0ayie zayie
  • Воркер получает задание, пытается подобрать значение из указанного в таске диапазона, которое даст такой же md5-хеш. Такое значение может быть, а может и не быть. О результате воркер сообщает мастеру, который печатает отчёт на stdout.
  • Получение результата мастером означает, что воркер освободился и может получить следующий таск (если таковые еще есть).
  • Диапазоны могут быть заданы некорректно.
    • zzz 000 -- нарушение правила lower меньше upper.
    • 0000 zz -- в upper меньше символов, чем в lower.
    • aaaa aaAz -- символ A не входит в разрешенный алфавит
  • Помимо некорректных диапазонов, ошибка может возникать при парсинге строки, и некорректном формате md5-суммы.
  • Столкнувшись с ошибкой, воркер должен "упасть" (завершить работу).
  • Эту ситуацию должен отловить мастер и запустить вместо упавшего воркера нового. Проблемное задание при этом выбрасывается, но на stderr должен быть отчёт от мастера.
  • Если воркер завершил обработку задачи без ошибок, то этот воркер должен быть переиспользован для одного из следующих заданий (если таковые будут). Т.е. допускается создание воркеров по мере необходимости, но не допускается создание/пересоздание воркеров для каждого нового задания.
  • Завершение работы программы происходит при достижении конца stdin и завершении обработки всех начатых заданий.

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

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

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


Уже имеющиеся решения:

Данную задачу мы со swizard-ом сформулировали именно таким образом, чтобы получить более-менее адекватное приближение к реальным задачам.

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

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

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

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

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


Небольшое примечание специально для тех, кто любит сравнивать размеры программ по количеству физических строк. Это довольно неблагодарное занятие хотя бы потому, что у каждого разработчика свой стиль кодирования. Поэтому, если есть желание подсчитывать количество строк, то имеет смысл хотя бы поудалять из исходника пустые строки и строки, которые содержат только открывающие/закрывающие скобки. Например, пропустив текст через такой простенький Ruby-скрипт:
ARGF.each_line do |line|
 if line =~ /(\d|\w)/
  puts line
 end
end