На erlang-questions запостили новое сравнение с участием Эрланга, кроме него там участвует C++/CORBA и Glasgow distributed Haskell. Область применения — традиционный телеком. Исследование проводилось в течение 3.5 лет Motorola Software, Systems Engineering Research Group и Heriot-Watt University. По содержанию обе бумаги вроде одинаковы: 1-я, 2-я
Здравствуйте, Курилка, Вы писали:
К>На erlang-questions запостили новое сравнение с участием Эрланга, кроме него там участвует C++/CORBA и Glasgow distributed Haskell. Область применения — традиционный телеком. Исследование проводилось в течение 3.5 лет Motorola Software, Systems Engineering Research Group и Heriot-Watt University. По содержанию обе бумаги вроде одинаковы: 1-я, 2-я
Здравствуйте, Курилка, Вы писали:
К>На erlang-questions запостили новое сравнение с участием Эрланга, кроме него там участвует C++/CORBA и Glasgow distributed Haskell. Область применения — традиционный телеком. Исследование проводилось в течение 3.5 лет Motorola Software, Systems Engineering Research Group и Heriot-Watt University. По содержанию обе бумаги вроде одинаковы: 1-я, 2-я
Суперская бумаженция.
Can productivity and maintainability be improved?
Yes, using source lines of code (SLOC) as a metric, both the Erlang
DM and DCC are less than a third of the size of the C++ counterpart
(Table 2). Moreover, much of the Erlang DCC is a reusable generic
server (Table 3). The reasons for the reduced programming effort are that
coding for the successful case saves 27%, high-level communications save
22%, and automatic memory management saves a further 11% (Tables 4
and 5). These productivity results are consistent with other measure-
ments [30], and with developer folklore.
Ну вот, и ответ на вопрос в соседней ветке — чем же именно Эрланг помогает в телекоме.
The reasons for the reduced programming effort are
1) coding for the successful case saves 27%,
Это Эрланговский подход к обработке ошибок — принцип let it crash.
2) high-level communications save 22%,
Это Эрланговская распределенка.
3) and automatic memory management saves a further 11%
А это GC.
Три основных фактора, сокращающий объем кода, и существенно влияющих на сроки разработки. Познавателно поглядеть на раскладку в процентах, сколько занимает defensive code (код обнаружения и корректной обработки ошибок в Эрланге и С++)
Code Type C++ Code RCS C libraries
Application 19.2% 12.1%
Defensive 25.3% 24.2%
Communication 22.1% 5.6%
Memory management 11.3% 7.1%
Type declarations 11.2% 11.6%
Defines 1.1% 23.6%
Includes 8.1% 8.6%
Process management 1.9% 7.1%
Эрланг:
Application 62.2%
Defensive 0.5%
Communication 15.1%
Memory management 0.0%
Type declarations 4.9%
Defines 5.4%
Includes 2.4%
Process management 9.5%
Можно ввести понятие "КПД Языка". Смотрите — у Эрланга прикладная логика 62% кода. У С++ — 19%. Такая вот ерунда, старички.
У языка 1С, правда, этот коэффициент будет около 95% . Как и у любого DSL. Отсюда мораль — DSL, это, в принципе, очень даже хорошо.
Здравствуйте, Gaperton, Вы писали:
G>У языка 1С, правда, этот коэффициент будет около 95% . Как и у любого DSL. Отсюда мораль — DSL, это, в принципе, очень даже хорошо.
Небольшая поправка. 1С — это Жлабэйсик с русифицированным синтаксисом. ДСЛ-я там не ма. Они просто преоставляют готовую библоитеку доступа к предметно-ориентированному хранилищу данных. В общем, Эксес переросток.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Курилка, Вы писали:
К>На erlang-questions запостили новое сравнение с участием Эрланга, кроме него там участвует C++/CORBA и Glasgow distributed Haskell. Область применения — традиционный телеком. Исследование проводилось в течение 3.5 лет Motorola Software, Systems Engineering Research Group и Heriot-Watt University. По содержанию обе бумаги вроде одинаковы: 1-я, 2-я
Ахринеть. Код:
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 successfullyif (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");
}
}
легко сократить до:
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
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
RETURN_STATUS ret_status = m_ici_io_ptr->send(&ici_msg_object);
// Check that message was sent successfullyif (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");
}
}
т.е. 26 строк против 37. А затем преобразовать его к той же парадигме let it crash (а использование исключений уже давно рекомендовано Страуструпом и поддерживается в C++ основными компиляторами уже лет пятнадцать):
// Send message to the DMTX task
RETURN_STATUS ret_status = m_ici_io_ptr->send(&ici_msg_object);
// Check that message was sent successfullyif (ret_status != SUCCESS)
// Report problem when sending ICI messagethrow IciMessageSendError(
MAJOR, SZ_ERR_MSG_ERR_OPCODE, __FILE__, __LINE__,
"DataMobilityRxProcessor processUnsupVer: failure sending "
" device info message to DMTX");
а еще лучше -- заставить порождать это исключение в методе m_ici_io_ptr->send. Тогда код станет еще компактнее:
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
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
m_ici_io_ptr->send(&ici_msg_object);
}
Что мешало разработчикам C++ проектов сразу писать в таком стиле? C++ или человеческий фактор?
Подобные сравнения лучше отложить до момента, когда на Erlang-е начнут программировать столько же ламеров, сколько на C++.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>а еще лучше -- заставить порождать это исключение в методе m_ici_io_ptr->send. Тогда код станет еще компактнее: E>
E>void DataMobilityRxProcessor::processUnsupVer(void)
E>{
E> // Create ICI message object to send to DMTX so it sends a Device Info
E> // message to Q1 and Q2 clients
E> IciMsg ici_msg_object( MM_DEVICE_INFO_OPC, ICI_DMTX_TASK_ID, sizeof( MM_DEVICE_INFO_MSG));
E> // Retrieve ICI message buffer pointer
E> MM_DEVICE_INFO_MSG * msg_ptr = (MM_DEVICE_INFO_MSG *)ici_msg_object.getIciMsgBufPtr();
E> // Populate message buffer
E> SET_MM_DEVICE_INFO_DEVICE_TYPE( msg_ptr, SERVER);
E> SET_MM_DEVICE_INFO_NUM_VER_SUPPORTED( msg_ptr, NUM_VER_SUPPORTED);
E> SET_MM_DEVICE_INFO_FIRST_SUP_PROTO_VERS( msg_ptr, PROTO_VERSION_ONE);
E> // Send message to the DMTX task
E> m_ici_io_ptr->send(&ici_msg_object);
E>}
E>
Кю.
Это разве хороший С++ный код?
Плюс ты еще потерял человекочитаемое сообщение об ошибке.
Надо так:
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<MM_DEVICE_INFO_MSG> msg(ICI_DMTX_TASK_ID);//MM_DEVICE_INFO_OPC скорей всего можно так или иначе получить из MM_DEVICE_INFO_MSG
msg->deviceType(SERVER);
msg->numVerSupported(NUM_VER_SUPPORTED);
msg->firstSupProtoVers(PROTO_VERSION_ONE);
// Send message to the DMTX task
IO_CHECK(m_ici_io_ptr->send(&msg), MAJOR, "failure sending device info message to DMTX");
}
ЗЫ А вобще спорить с тем что С++ мягко говоря не самый удачный язык для распределенки и прочей паралельности глупою.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Константин Л., Вы писали:
КЛ>Код eao197 и твой не равноценны, хотя бы потому, что твой нерабочий
И что же ты в нем такого не рабочего то нашол?
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, eao197, Вы писали:
E>Подобные сравнения лучше отложить до момента, когда на Erlang-е начнут программировать столько же ламеров, сколько на C++.
Поясню свою мысль: даже при идеальном кодировании, C++ не догонит Erlang по компактности и, вероятно, корректности, распределенных приложений (особенно в телекоме). DSL (коим мне представляется Erlang на данных задачах) -- он и в Африке DSL. Но вот разрывы в показателях между нормальными C++ программами и аналогичными Erlang-овскими уже не будут составлять 7-8 раз, а раза эдак 2-3.
Собственно, на место C++ можно подставить любой мейнстримовый (и не только) императивный язык: Java, C#, ObjectPascal, Eiffel, Modula, Ada... -- слишком они универсальные для того чтобы играть с Erlang-ом на его поле.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
E>Собственно, на место C++ можно подставить любой мейнстримовый (и не только) императивный язык: Java, C#, ObjectPascal, Eiffel, Modula, Ada... -- слишком они универсальные для того чтобы играть с Erlang-ом на его поле.
Это, в принципе, и есть результат второй работы — high level concurrency abstracts. Единственная причина, по которой они выбрали Эрланг для дальнейших разработок — это наличие таких абстракций в языке, его промышленное качество и наличие развитых библиотек. Если бы такие же абстракции были легкодоступны в С++, они бы выбрали С++. Если бы Glasgow Distributed Haskell был бы промышленного качества, они бы выбрали его
Здравствуйте, Mamut, Вы писали:
E>>Собственно, на место C++ можно подставить любой мейнстримовый (и не только) императивный язык: Java, C#, ObjectPascal, Eiffel, Modula, Ada... -- слишком они универсальные для того чтобы играть с Erlang-ом на его поле.
M>Это, в принципе, и есть результат второй работы — high level concurrency abstracts. Единственная причина, по которой они выбрали Эрланг для дальнейших разработок — это наличие таких абстракций в языке, его промышленное качество и наличие развитых библиотек. Если бы такие же абстракции были легкодоступны в С++, они бы выбрали С++. Если бы Glasgow Distributed Haskell был бы промышленного качества, они бы выбрали его
Сегодня читая одну книжицу, наткнулся на фрагмент, который, как мне кажется, показывает, почему подобные сравнения всегда будут в пользу "немейнстримовых" подходов:
"...Исследование попыток внести изменения в принципы работы организации показывает, что пилотные проекты, адаптированные к конкретным условиям, практически всегда оказываются успешными, тогда как навязанные третьими лицами универсальные модели, основанные на обобщенном опыте, всегда проваливаются. Причина заключается в том, что проявление лидерских качеств, раскрытие творческого потенциала, обострение мотивации и рост ответственности всегда возрастают с появлением новых вызовов и сходит на нет при многократном повторении. Если что-то принято делать определенным образом и это никак нельзя усовершенствовать, задача становится менее захватывающей и менее интригующей, чем открытие совершенно новых, неизвестных ранее путей..."
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, Константин Л., Вы писали:
КЛ>>Код eao197 и твой не равноценны, хотя бы потому, что твой нерабочий WH>И что же ты в нем такого не рабочего то нашол?
ну не компилицца он . eao197 поменял его так, чтобы он оставался компилябельным. Твой — нет. А вообще, наверное твой лучше .
Здравствуйте, Константин Л., Вы писали:
КЛ>ну не компилицца он . eao197 поменял его так, чтобы он оставался компилябельным. Твой — нет. А вообще, наверное твой лучше .
Если уж придиратся то у eao197 не обрабатываются ошибки send.
А перевод системы с кодов возврата на исключения всеравно потребует переделки всего кода.
Так что если уж редизайнить то редизайнить как следует.
Хотя тот код что у меня тоже не идеал но для того чтобы сделать его лучше нужно знать о системе все.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, Курилка, Вы писали:
E>Ахринеть. Код: E>void DataMobilityRxProcessor::processUnsupVer(void)
хъ E>Что мешало разработчикам C++ проектов сразу писать в таком стиле? C++ или человеческий фактор?
processUnsupVer — конечно, очень типовой код, я понимаю. Вот такой код — кусочек разбора IP-датаграммы — это, наверно, реже в телеком-приложениях встречается:
Кстати, эксцепшены, которые ты бросаешь в С++, тебе придется бросать ручками. И ручками постоянно паковать туда символическую информацию. Также крайне любопытно, что ты будешь делать при вылете эксцепшна в потоке. Ну поймал ты его наверху в тред-функции — типа классно, let it crash и все такое. Что будем делать с потоком? А что будешь делать с его примитивами синхронизации, на котором стоят в блокировке другие потоки?
E>Подобные сравнения лучше отложить до момента, когда на Erlang-е начнут программировать столько же ламеров, сколько на C++.
В этом сравнении на Эрланге писали самые что ни на есть ламеры, дружище. Они язык и платформу изучали в процессе самого сравнения.
Gaperton wrote: > Ну поймал ты его наверху в тред-функции — типа классно, let it > crash и все такое. Что будем делать с потоком? А что будешь делать с его > примитивами синхронизации, на котором стоят в блокировке другие потоки?
Я в таких случаях ВСЕГДА использую scoped-блокировки, которые сами
автоматически отмотаются при обработке исключения.
Здравствуйте, Cyberax, Вы писали:
C>Gaperton wrote: >> Ну поймал ты его наверху в тред-функции — типа классно, let it >> crash и все такое. Что будем делать с потоком? А что будешь делать с его >> примитивами синхронизации, на котором стоят в блокировке другие потоки? C>Я в таких случаях ВСЕГДА использую scoped-блокировки, которые сами C>автоматически отмотаются при обработке исключения.
Здравствуйте, Gaperton, Вы писали:
G>processUnsupVer — конечно, очень типовой код, я понимаю. Вот такой код — кусочек разбора IP-датаграммы — это, наверно, реже в телеком-приложениях встречается:
G>-define(IP_VERSION, 4). G>-define(IP_MIN_HDR_LEN, 5).
G>
Горазд ты примеры из документации дергать.
А покажи-ка, дружище, код чтения ASCIIZ значений из входного потока. Когда байтовое значение прекращается первым нулевым байтом, а следом идет либо другое ASCIIZ-значение, либо поле с фиксированным размером. Как это будет на Erlang-е? А на плюсах что-то вроде:
тоже, кстати, код из области телекома.
G>Кстати, эксцепшены, которые ты бросаешь в С++, тебе придется бросать ручками. И ручками постоянно паковать туда символическую информацию. Также крайне любопытно, что ты будешь делать при вылете эксцепшна в потоке. Ну поймал ты его наверху в тред-функции — типа классно, let it crash и все такое. Что будем делать с потоком? А что будешь делать с его примитивами синхронизации, на котором стоят в блокировке другие потоки?
А про понятие exception safety за пределами C++ никто не знает, надо полагать?
E>>Подобные сравнения лучше отложить до момента, когда на Erlang-е начнут программировать столько же ламеров, сколько на C++. G>В этом сравнении на Эрланге писали самые что ни на есть ламеры, дружище. Они язык и платформу изучали в процессе самого сравнения.
Тогда, я полагаю, их Erlang-овский код можно ужать в той же степени, как и их C++ный код.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
G>>Повторим на плюсах?
E>Горазд ты примеры из документации дергать.
Я так понял, тебе понятно, насколько этот код на плюсах возрастет в объеме. Или нет?
E>А покажи-ка, дружище, код чтения ASCIIZ значений из входного потока. Когда байтовое значение прекращается первым нулевым байтом, а следом идет либо другое ASCIIZ-значение, либо поле с фиксированным размером. Как это будет на Erlang-е? А на плюсах что-то вроде:
E>
{ Stream1, ServiceType, SourceAddrTon, SourceAddr, ... ] = parse( Stream, [ string, 2, 4, ... ] ),
здесь я задаю параметрами partition как мне выделять из потока (поток это бинари) — строку или число (размер в байтах). Функция parse пишется один раз. Написать?
Чтение я могу разбить на несколько строк — на столько, сколько захочу. Если у меня будут разные опции форматов с числовыми аргументами, я определю манипуляторы, например:
А еще я могу задавать жутко хитрые манипуляторы, например такие
{ Stream1, X, { Y, Z } } = parse( Stream, [ string, fun( << A:3, B:5, ?MY_CONSTANT, _/binary >> ) -> { A, B } end ] ).
При этом, я сохраняю возможность применять паттерн-матчинг на бинарных данных когда захочу. Ну и естественно, никаких проблем с опциональными параметрами у меня не будет — я сделаю просто
OptParms = parse( StreamN, opt_parms() );
Вот так, дружище. Не слишком страшно получается? И заметь, никакого ООП и перегруженных операторов.
G>>Кстати, эксцепшены, которые ты бросаешь в С++, тебе придется бросать ручками. И ручками постоянно паковать туда символическую информацию. Также крайне любопытно, что ты будешь делать при вылете эксцепшна в потоке. Ну поймал ты его наверху в тред-функции — типа классно, let it crash и все такое. Что будем делать с потоком? А что будешь делать с его примитивами синхронизации, на котором стоят в блокировке другие потоки?
E>А про понятие exception safety за пределами C++ никто не знает, надо полагать?
Угу, а как насчет разделяемых данных, которые остались в нецелостном состоянии? И все-таки, что именно ты предлагаешь делать с потоком?
E>>>Подобные сравнения лучше отложить до момента, когда на Erlang-е начнут программировать столько же ламеров, сколько на C++. G>>В этом сравнении на Эрланге писали самые что ни на есть ламеры, дружище. Они язык и платформу изучали в процессе самого сравнения.
E>Тогда, я полагаю, их Erlang-овский код можно ужать в той же степени, как и их C++ный код.
Не исключено. Но врят ли — Эрланг все таки проще С++ на пару порядков, там сложнее налажать.