Давно ничего не писал на тему программизма. Особенно и нечего было писать. Работа над приоритетами в SO-5.6 идет туго, но, надеюсь, все-таки идет. Плюс ушло несколько дней на перелопачивание и обработку большого количества фотографий (блин, фотограф -- это нисколько не простая профессия). Но вот на RSDN и LOR-е всплыло две темы, которые оставили меня в полном недоумении.
понедельник, 29 июня 2015 г.
понедельник, 15 июня 2015 г.
[prog.actors] Ув.тов.netch80 о принципах построения систем на акторах (Erlang)
Чтение форумных разборок -- это поиск редких жемчужин в огромных кучах говна. Но иногда эти поиски приносят уникальные результаты. Вот, например, соображения одного из самых толковых RSDN-неров, netch80, о том, как нужно и как не нужно делать приложения с большим количеством акторов внутри. Тов.netch80 писал об Erlang-е, поэтому в его рассказе так же подчеркиваются достоинства Erlang-а. Но к похожим выводам пришли и мы на основании опыта использования SObjectizer, например, в плане количества ждущих обработке сообщений и соотношения количества текущих активностей к количеству доступных ядер. Утащу текст целиком к себе, дабы потом было проще искать:
суббота, 30 мая 2015 г.
[prog.flame] Забавно, когда в качестве доказательства приводят неважно написанный C-шный код
В обсуждении релиза SObjectizer-5.5.5 на LOR-е в очередной раз всплыла идея о том, что приложение на акторах нужно писать на Erlang-е, а не на C++. И уж если производительности будет недостаточно, то тогда переписать узкие места на C в виде NIF-ов/драйверов:
Я и предложил нивелировать разрыв между C++, в данном случае, и чистым Erlang'ом с помощью NIF'ок, драйверов и пр. Ибо это элементарно проще, а по производительности будет идти ноздря в ноздрю с С++.
Идея не новая. Одна из вещей, которая серьезно портит эту идею, состоит в том, что писать нормальный и корректный код на C не просто. Как по мне, как гораздо сложнее, чем на C++. Ну да суть не столько в том, что C++ удобнее для написания надежного софта, чем C. А в том, какого качества C-шный код будут производить на свет обычные Erlang-еры, которые C видят лишь время от времени?
Собственно, приведенный на LOR-е код является тому подтверждением...
четверг, 2 октября 2014 г.
вторник, 29 июля 2014 г.
[prog] Интересные ссылки на тему overload control
В продолжение вчерашней темы. Вот несколько ссылок на интересные материалы, которые попались в Интернете на эту тему. Если кто-то сможет поделиться еще чем-то, буду очень признателен.
Adaptive Overload Control for Busy Internet Servers, 2003 год. PDF-ка на 14 страниц от разработчиков фреймворка SEDA. Читать оттуда можно лишь несколько страниц, где описываются особенности трех механизмов контроля за нагрузкой на сервисы. Ценность этой статьи в том, что она явно показывает, что хороший механизм защиты от перегрузки должен использовать максимум знаний о предметной области, а само прикладное решение должно изначально строится с оглядкой на действие механизма защиты от перегрузки.
Следующие три ссылки -- это статьи Макса Лапшина, стоящего за Erlyvideo/Flussonic:
Overload Protection 1 и Overload Protection 2 -- две первых части из серии статей о том, как в Erlyvideo справлялись с пиковыми нагрузками (в каждой статье есть ссылки на следующие статьи серии, так что легко при желании прочитать их все, оно того стоит, ИМХО).
Про эрланг vs XXX: интроспекция для отладки. Очень интересная заметка. Не столько про защиту от перегрузок, сколько о том, что активный Elrang-юзер считает реально ценным и полезным в такой мощном инструменте, как Erlang.
Лично для меня напрашивается следующий практический вывод: базовый фреймворк должен предоставлять лишь базовые средства. Например, лимиты на максимальные размеры очередей, диагностика и простейшая реакция на их превышение. Возможно, еще одну штуку нужно дать пользователю на уровне базового фреймворка -- это получить текущую длину очереди сообщений агента. Собственно и все.
Более сложные и изощренные механизмы должны предоставлять заточенные под конкретные задачи прикладные библиотеки/фреймворки, построенные на основе базового фреймворка.
понедельник, 26 сентября 2011 г.
[prog] Вспомнился случай, когда хотелось иметь горячую замену кода
Во время чтения вот этого обсуждения, в котором зашел разговор о применимости горячей замены кода (одна из важнейших фич языка Erlang), вспомнил ситуацию, когда такая замена не помешала бы мне в C++.
Есть в нашем SMS-шлюзе специальный компонент под названием send.bufferizator. Его задачей является сглаживание резких пиков в количестве исходящих сообщений. Например, происходит какое-то событие и генерируется пачка сообщений, объем которой многократно превышает разрешенную пропускную способность. Скажем, клиенту разрешено 100 sms/sec, а он однократно сгенерировал 500, а затем в течении 5-10 секунд больше ничего не отсылает. В такой ситуации send.bufferizator вбирает в себя всю пачку и отдает ее содержимое не превышая разрешенной скорости – т.е. эти 500 сообщений выйдут из send.bufferizator-а в течении 5 секунд по 100 в секунду.
Данные внутри send.bufferizator хранятся в ОП, не в БД. Хранение в долговременной памяти не нужно, т.к. наш протокол обмена сообщениями устроен так, что операция отсылки является безопасной (идемпотентной, если употребить умный термин) – до тех пор пока шлюз не пришлет подтверждение клиент может (и должен) повторять попытки отсылки. Поэтому, если send.bufferizator по какой-то причине перестает работать, то теряется содержимое его очередей. Но это не страшно, т.к. никаких подтверждений мы клиенту не отсылали и клиент вновь повторит их отправку. Тем не менее, при больших скоростях send.bufferizator может содержать у себя по несколько тысяч сообщений, поэтому прерывать его работу не очень хорошо.
Но это все преамбула. Теперь сама история. Однажды среди ночи меня разбудил телефонный звонок из нашей службы техподдержки с просьбой разобраться с проблемой, с которой раньше сталкиваться никому не приходилось. Было видно, что один из send.bufferizator-ов реагирует на внешние раздражители, но сообщения через себя не пропускает.
Проблема оказалась любопытная – при обработке одной из ситуаций я лишний раз декрементировал текущий показатель нагрузки и, поскольку это был unsigned int, значение переходило через ноль и получалось 0xffffffff. Из-за чего send.bufferizator считал, что нагрузка сейчас многократно превышена и новые сообщения должны приостанавливаться пока она не снизится. А снизится она, понятное дело, не могла.
Лекарство, как и во многих других случаях – “выйти и зайти”, т.е. рестартовать компонент. Однако, ошибка в коде оставалась, я ее быстро исправил. Но для обновления всех компонентов пришлось делать их рестарты, естественно, с потерей текущего содержимого ОП. И вот это был тот самый случай, когда горячая замена только кода работающего модуля, без потери его текущих данных, пришлась бы очень кстати. Т.к. тогда этот bugfix прошел бы вообще никем не замеченный.
Мораль сей басни такова. Если кто-то считает, что некая фича является бесполезной потому, что он не имеет перед глазами примеров ее применения, то это не значит, что фича действительно бесполезная. Скорее это просто отсутствие примеров здесь и сейчас. Но, в свою очередь, наличие примеров не делает фичу очень полезной и очень востребованной ;)
PS. Кстати, в той истории еще раз проявились законы Мерфи. Ошибка могла возникнуть в очень экзотической ситуации. А ситуация это сложилась поздно ночью.
PPS. Когда-то на глаза попадалась статья Practical Dynamic Software Updating for C в которой описывалась технология накатов бинарных обновлений на работающий C-шный код. Правда, не могу судить о том, насколько все это жизнеспособно и применимо. Так же не знаю и о дальнейшей судьбе данного исследования.
PPPS. Не могу отказать себе в удовольствии с сарказмом пройтись по цитате, которую thesz вырвал из доклада “Running a startup on Haskell”: Deploying our code is a simple matter of redirecting a symlink, then bouncing the server. Downtime during a deploy is a fraction of a second. Ну прям бином Ньютона ребята выдумали, никто кроме хаскелистов до такого додуматься не смог бы, поэтому этим нужно непременно хвастаться! Хотя такому приему уже сто лет в обед и его переизобретает, имхо, любой разработчик, которому приходится плотно сталкиваться с проблемой развертывания бинарников.
понедельник, 19 сентября 2011 г.
[prog] Презентация о фреймворке Akka: Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Презентация не новая, но попалась мне на глаза только сегодня. Любопытно.
Вообще, смотреть такие презентации без изрядной доли иронии и сарказма я лично не могу. Далеко не новые идеи преподносятся как что-то из области cutting edge :) И это даже если не брать в расчет Erlang, где почти все показанное в презентации эксплуатирует с конца 80-х (правда, широко известен он стал намного позже). Мы в КБСП подобный подход переоткрыли и начали применять в середине 90-х. Что воплотилось затем уже в Интервэйле в наш внутренний инструмент SObjectizer-4, который не много, ни мало, а уже девять лет используется нами для разработки С++ных приложений.
Тем не менее, жизнь забавная штука. Я, например, постоянно забываю, что уже выросло огромное количество разработчиков, которые приобщились к программированию уже после 2000-го и которые начинали с Java, а то и с C#. И, если начало было в обнимку с Java, то наверняка вобрали в себя такую дурную привычку Java-сообщества, как игнорирование полезных вещей до тех пор, пока не появится какой-то раскрученный фреймворк, который протолкнет эти вещи в мейнстрим (да, я большой любитель кидаться камнями в Java-огород). Посему такие презентации очень полезная штука.
По поводу показанных в презентации примеров есть у меня несколько сомнений в правильности выбранных авторами Akka подходов.
Во-первых, для сложных актеров метод onReceive с последующим ручным определением типа сообщения посредством множества обращений к instanceof, на мой взгляд, не есть хорошо. Это черевато некрасивым кодом, провоцирующим ошибки и сложным в сопровождении. Имхо, задача фреймворка определить тип сообщения и вызвать подходящий для сообщения метод. Это как раз то, за счет чего фреймворки вроде MFC упростили программирование под Windows, когда большая WndProc с одним switch-ем внутри была разбита на простые методы, каждый из которых обрабатывает всего одно Windows-сообщение.
Во-вторых, как-то я не очень понял на счет распределенных актеров. Мне показалось, что при работе с такими актерами в коде явно придется проводить грань – вот этот актер локальный, а этот удаленный и к нему нужно подключаться. Если это так, то я бы предпочел иную схему, когда расположение актера не нужно руками в коде. Это должно делаться автоматически на уровне фреймворка и конфигурации приложения.
В-третьих, я не понял, зачем в агентный фреймворк засовывать еще и STM. Шоб было усё и зразу? ;)
Еще одна мысль после просмотра презентации – очень похоже, что агентные фреймворки для нативных и управляемых языков должны развиваться в несколько разных направлениях.
среда, 14 апреля 2010 г.
[prog] Еще одна презентация про использование Erlang: Макс Лапшин о Erlyvideo
Сама презентация:
Её обсуждение в ЖЖ автора: http://levgem.livejournal.com/285670.html
Из того, что там изложено я не могу спорить только с тем, что в Erlang есть возможность “горячей” замены кода “из коробки”.
Есть так же несколько вещей, которые я понять не могу:
- ладно в C++ной программе легко пройтись по чужой памяти и уронить таким образом все приложение. Но зачем подобные страшилки о Java рассказывать?
- зачем в приложениях на Erlang вручную управлять памятью?
А еще мне очень не нравится, когда между C и C++ ставят знак равенства (во всей презентации речь идет то об C++, то о C, как будто это одно и то же).
PS. И нефиг серьезные вещи на Objective-C делать ;)
среда, 20 января 2010 г.
[comp.prog] Ссылки про знаменитый AXD 301 – большущий флаг всех эрлангистов
Как только упоминается язык Erlang, так сразу в качестве козырного туза предъявляется проект AXD 301 – ATM switch (телефонный цифровой коммутатор, если я правильно перевожу это на русский) от Ericsson-а. Поскольку практически всегда, когда речь заходит о нем, приходиться искать в Интернете статьи с указанием объема кода и количества разработчиков, то решил некоторые из них опубликовать здесь. Итак:
AXD 301-A new generation ATM switching system – рекламное-обзорное описание самого устройства. 1998 год.
Ulf Wiger’s Four-fold Increase in Productivity and Quality – презентация с рассказом о том, как программирование на Erlang увеличивает скорость и качество разработки. С примером AXD 301, естественно. 2001 год.
Joe Armstrong’s Concurrency Oriented Programming in Erlang – доклад о конкурентном программировании на Erlang. 2002 год (и тот же доклад, но уже в 2003 году).
Joe Armstrong’s Making reliable distributed systems in the presence of sodware errors – диссертация Армстронга, в которой он говорит, в том числе, и об AXD 301. 2003 год.
Mats Cronqvist’s Troubleshooting a Large Erlang System – небольшая статья о том, как разрабатывался софт для AXD 301. 2004 год.
Интересен рост количества строк в Erlang-овой части AXD от публикации к публикации. Ульф Виджер указывает 1M (+ еще 260K в самом OTP). Армстронг через год говорит об 1.7M (хотя в диссертации указана цифра в 1136150 строк кода). А Кронквист через два года – о 2.1M (хотя не факт, что там считались только Erlang-овские строки). Либо софт AXD 301 все время дорабатывают, либо со временем партизаны в воспоминаниях ветеранов становятся все толще и толще ;)
Меня впечатляют цифры из презентации Ульфа Виджера:
- 1M строк кода на Erlang-е;
- 400K строк на C/C++;
- 13K строк на Java;
- плюс к тому около 500K строк кода на C, который работал на т.н. device processor-ах;
- плюс к тому около 100K строк кода на C в стороннем ПО (запуском которого занимались программы на Erlang-е);
- плюс к тому 240K строк на Erlang-е, 460K строк на C++ и 15K строк на Java, которые входили в саму реализацию Erlang/OTP.
В статье Кронквиста указывается, что писало код около 300 человек, хотя раньше я слышал другие цифры – порядка 150.
Просьба к читателям: когда-то я читал то ли статью Армстронга (а может и не Армстронга), то ли его интервью, в котором он подробнее рассказывал о разработке AXD 301. Там, кажется, были более подробные цифры по разработчикам. Кажется, что 50 человек писали Erlang-овую часть и еще около 100 человек – C/C++ные и Java-вские модули. Еще там Армстронг указывал, что одним из факторов успеха проекта было то, что удалось всех разработчиков собрать в едином центре, что существенно сокращало издержки на коммуникации внутри коллектива. Сам я эту ссылку найти сейчас не смог. Буду признателен, если кто-то ею поделится.
среда, 16 декабря 2009 г.
[comp.prog] Презентация об использовании Erlang в Facebook
Erlang at Facebook – интересная PDF-а на 40 страниц.
Erlang использовался для реализации части сервиса Chat в Facebook. Прототип сервиса был создан в январе 2007, затем командой из 4 человек доводился до ума до осени 2007-го. В феврале 2008 проект был запущен в тестовую эксплуатацию.
PS. Раз уж речь зашла о Web-проекте, который активно использовал AJAX для обмена информацией с сервером, можно упомянуть свежий блог-пост Джо Армстронга об Web-сокетах. В котором он пророчит неминуемую смерть подобным AJAX-овским наворотам.
четверг, 3 декабря 2009 г.
[comp.prog.flame] И еще одно сравнение C++ с Erlang (британскими учеными на этот раз)
На RSDN-е проскочила ссылка на очередное сравнение C++ и Erlang, на этот раз выполненное в Motorola Labs совместно с университетом Heriot-Watt из Эдинбурга. Вот презентация этого сравнения:
При просмотре презентации я обратил внимание на один подозрительный момент – там где идет сравнение объемов кода на слайде 27. Чтобы убедиться в их обоснованности, я нашел PDF-ку с описанием этой работы – вот она: High-Level Distribution for the Rapid Production of Robust Telecoms Software: Comparing C++ and Erlang. А вот эти фрагменты крупным планом. На erlang-е:
| sz_dme_dmtx:cast(device_info) |
И оригинальный фрагмент на C++, который, якобы, делает тоже самое:
| void DataMobilityRxProcessor::processUnsupVer(void) { MSG_PTR msg_buf_ptr; MM_DEVICE_INFO_MSG *msg_ptr; RETURN_STATUS ret_status; UINT16 msg_size; // Determine size of ici message msg_size = sizeof( MM_DEVICE_INFO_MSG); // Create ICI message object to send to DMTX so it sends a Device Info // message to Q1 and Q2 clients IciMsg ici_msg_object( MM_DEVICE_INFO_OPC, ICI_DMTX_TASK_ID, msg_size); // Retrieve ICI message buffer pointer msg_buf_ptr = ici_msg_object.getIciMsgBufPtr(); // Typecast pointer from (void *) to (MM_DEVICE_INFO_MSG *) msg_ptr = (MM_DEVICE_INFO_MSG *)msg_buf_ptr; // Populate message buffer SET_MM_DEVICE_INFO_DEVICE_TYPE( msg_ptr, SERVER); SET_MM_DEVICE_INFO_NUM_VER_SUPPORTED( msg_ptr, NUM_VER_SUPPORTED); SET_MM_DEVICE_INFO_FIRST_SUP_PROTO_VERS( msg_ptr, PROTO_VERSION_ONE); // Send message to the DMTX task ret_status = m_ici_io_ptr->send(&ici_msg_object); // Check that message was sent successfully if (ret_status != SUCCESS) { // Report problem when sending ICI message sz_err_msg( MAJOR, SZ_ERR_MSG_ERR_OPCODE, __FILE__, __LINE__, "DataMobilityRxProcessor processUnsupVer: failure sending " " device info message to DMTX"); |
Оставим сейчас в стороне логическое соответствие этих двух фрагментов (действительно, пусть в Erlang программе сущность device_info сразу рождается полностью корректно сформированной и в C++ сделать тоже самое ну никак нельзя). Достаточно просто взглянуть на C++ный код и ужаснуться.
Даже не переделывая ничего в дизайне программы его можно (и нужно) очень сильно сократить. Ну хотя бы вот так:
| void DataMobilityRxProcessor::processUnsupVer(void) { // Create ICI message object to send to DMTX so it sends a Device Info // message to Q1 and Q2 clients IciMsg ici_msg_object( MM_DEVICE_INFO_OPC, ICI_DMTX_TASK_ID, sizeof( MM_DEVICE_INFO_MSG ) ); // Retrieve ICI message buffer pointer and // Typecast pointer from (void *) to (MM_DEVICE_INFO_MSG *) MM_DEVICE_INFO_MSG * msg_ptr = (MM_DEVICE_INFO_MSG *)ici_msg_object.getIciMsgBufPtr(); // Populate message buffer SET_MM_DEVICE_INFO_DEVICE_TYPE( msg_ptr, SERVER); SET_MM_DEVICE_INFO_NUM_VER_SUPPORTED( msg_ptr, NUM_VER_SUPPORTED); SET_MM_DEVICE_INFO_FIRST_SUP_PROTO_VERS( msg_ptr, PROTO_VERSION_ONE); // Send message to the DMTX task const RETURN_STATUS ret_status = m_ici_io_ptr->send(&ici_msg_object); // Check that message was sent successfully if (ret_status != SUCCESS) { // Report problem when sending ICI message sz_err_msg( MAJOR, SZ_ERR_MSG_ERR_OPCODE, __FILE__, __LINE__, "DataMobilityRxProcessor processUnsupVer: failure sending " " device info message to DMTX"); |
Уже получается 27 строк вместо 35 (сокращение на 22%, если пародировать подобные отчеты). А если поступить нормально и вынести все манипуляции с msg_ptr во вспомогательную функцию, то получится еще компактнее:
| void DataMobilityRxProcessor::processUnsupVer(void) { // Create ICI message object to send to DMTX so it sends a Device Info // message to Q1 and Q2 clients IciMsg ici_msg_object( MM_DEVICE_INFO_OPC, ICI_DMTX_TASK_ID, sizeof( MM_DEVICE_INFO_MSG ) ); // Populate message buffer populateMessageBuffer( (MM_DEVICE_INFO_MSG *)ici_msg_object.getIciMsgBufPtr() ); // Send message to the DMTX task const RETURN_STATUS ret_status = m_ici_io_ptr->send(&ici_msg_object); // Check that message was sent successfully if (ret_status != SUCCESS) { // Report problem when sending ICI message sz_err_msg( MAJOR, SZ_ERR_MSG_ERR_OPCODE, __FILE__, __LINE__, "DataMobilityRxProcessor processUnsupVer: failure sending " " device info message to DMTX"); |
Почти в два раза меньше исходного варианта. Я бы пошел еще дальше, и повыбрасывал бы эти дебильные комментарии вида “Ща мы проверим успешность операции”, да и количество пустых строк подсократил бы. Конечно, однострочного “аналога” на Erlang-е не получилось бы, но процентов из 60% от исходного индусокода можно было бы выбросить смело.
Резюмируя хочется сказать, что C++ далеко не самый лучший язык программирования, и наверняка системы для телекома лучше писать на Erlang-е. Но! Когда на Erlang-е начнут писать такие же горе-программисты, которые написали процитированный C++ный код, то все достоинства Erlang-а одним махом станут его недостатками.
Эдинбург находится в Великобритании ;)
понедельник, 9 ноября 2009 г.
[comp.prog] Презентация Message-Passing Concurrency in Erlang от Ulf Wiger
27-ми страничная PDF-ка на 6Mb: Message-Passing Concurrency in Erlang.
Предупреждение. Для знакомых с Erlang-ом людей она может оказаться повторением уже известных вещей. Для не знакомых с Erlang-ом – малопонятной.
Меня впечатлила в презентации диаграмма производительности на 64-х ядерном процессоре Tilera Pro (это процессор той компании, которая недавно анонсировала 100-ядерный процессор).
PS. Чем больше смотрю на примеры Erlang-овых программ, тем больше меня терзает мысль, что это такой write-only язык: уж очень гремучей смесью выглядит функциональное программирование на динамически-типизированном языке.
PPS. Кстати, чтобы получить еще большее представление о специфике задач, для которых создавался Erlang (и о сложных конечных автоматах на Erlang), можно посмотреть еще и эту презентацию: Structured Network Programming того же автора.
