Показаны сообщения с ярлыком язык C++. Показать все сообщения
Показаны сообщения с ярлыком язык C++. Показать все сообщения

вторник, 11 июля 2023 г.

[prog.c++] Ну как так то?

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

Началось все с того, что разыскивая информацию про NAT/STUN/UPnP/port-forwarding и иже с ними, наткнулся на проект pjsip. Был приятно удивлен тому, насколько приятно он оформлен в плане количества документации. Не берусь судить о ее качестве, т.к. смотрел сильно мельком и по диагонали. Но первое впечатление: внушаить!

Под этим положительным впечатлением решил заглянуть в исходники. Ну, думаю, аккуратно написанный на чистом Си проект, надо же поучиться тому, как должен выглядеть хороший Сишный код. Заглянул в первый попавшийся файл:

четверг, 16 февраля 2023 г.

[prog.wow] Век живи, век учись: с указателем после освобождения ничего нельзя делать

Иногда флеймы на профильных ресурсах оказываются очень полезны. Вот свежий пример с LOR-а: "Навеяно свежей дырой в Xorg".

В двух словах: после освобождения указателя (через free в C или delete в C++) с указателем ничего нельзя делать (кроме как присвоить ему новое валидное значение).

Т.е. не то, что разыменовывать нельзя (это-то как раз понятно), но и вообще ничего нельзя: ни распечатать, ни сравнить с чем-нибудь (пусть даже и с NULL/nullptr), ни преобразовать в uintptr_t. НИЧЕГО. Любые попытки сделать что-то подобное есть UB.

Говорят, что у этого есть даже какое-то логическое обоснование. Но мне осознать сие не получается :)

Вышесказанное означает, что если у вас написано что-то подобное:

void data_cleanup(data * ptr) {
  if(ptr != NULL) {
    ... // Какие-то действия по очистке.
    free(ptr);
  }
  else {
    ... // Какие-то другие действия. Допустим, просто
        // печать в лог о том, что data_cleanup был вызван.
  }

  ... // Еще какие-то действия, которые не зависят от
      // значения ptr.

  // А здесь нужно еще что-то сделать если ptr не был NULL.
  if(ptr != NULL) { // (1)
    ... 
  }
}

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

Полагаю, что выйти из ситуации можно вот так:

void data_cleanup(data * ptr) {
  int not_null = ptr != NULL;
  if(not_null) {
    ... // Какие-то действия по очистке.
    free(ptr);
  }
  else {
    ... // Какие-то другие действия. Допустим, просто
        // печать в лог о том, что data_cleanup был вызван.
  }

  ... // Еще какие-то действия, которые не зависят от
      // значения ptr.

  // А здесь нужно еще что-то сделать если ptr не был NULL.
  if(not_null) {
    ... 
  }
}

Но это же нужно быть очень внимательным, чтобы не наступать на подобные грабли.

К счастью, в C++ при использовании умных указателей вроде shared_ptr и unique_ptr все не так страшно. Но вот если нужно записать что-то на чистой ламповой Сишечке или на старых плюсах, в которых умных указателей нет... То грустно.


Данное обсуждение заставило вспомнить еще про одну засаду с голыми указателями. Еще, если кто-то не знал или забыл, в Си и C++ нельзя просто так сравнивать на больше/меньше указатели одного типа. Грубо говоря, если у нас есть указатели a и b одного типа, то выражение (a<b) будет определено, только если a и b указывают на элементы одного массива (либо на элемент за последним элементом этого массива).

Правда, в C++, насколько я понимаю, можно воспользоваться std::less или std::greater из стандартной библиотеки. Поскольку для подобных компараторов определены специализации для указателей. Например, по поводу std::less на cppreference сказано буквально следующее: "A specialization of std::less for any pointer type yields the implementation-defined strict total order, even if the built-in < operator does not."

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

суббота, 27 июля 2019 г.

[work.thoughts] Мысля насчет расценок в зависимости от языка программирования

В последнее время, когда приходится писать код, делаю это либо на C++17, либо на C++14, либо на C++11. Либо, внезапно, на чистом C. C++98 уже давно не попадалось.

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

Но к чему я этим решил поделиться? А вот к чему.

Похоже, что нужно выстраивать ценник в зависимости от степени свежести стандарта языка программирования. Скажем, есть базовая цена для C++17 (для наших еб*ней с прицелом на заказчиков из РФ -- это где-то $25/hour для проекта от двух-трех месяцев длительностью без горящих сроков).

Тогда для C++14 будет базовая цена + 5%.

Для C++11: базовая цена + 25%. А если нужно жить с GCC ниже 4.8 или MSVS2013, то + 50%.

Для C++98: базовая цена * 2.

Для чистого C: базовая цена * 3.89. В случае, если заказчик согласен на частичный рефакторинг с постепенным затаскиванием C++ных частей в C-шную кодовую базу (или постепенный перевод с C на C++), то базовая цена * 2.17.

Ибо нех*й.

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

PS. Если кто-то остался один на один с древним C-шным или C++ным кодом, без которого вам не обойтись, но с которым вы не знаете, что делать, то вам сюда. И да, это реклама. Проплачена мной.

воскресенье, 19 марта 2017 г.

[prog.thougts] В очередной раз о нотации (в применении к C++)

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

Дело в том, что в C++ нет общепринятого и стандартизированного соглашения о стиле оформления кода. На мой взгляд, это есть хорошо, но это мое личное мнение. Важнее то, что в C++ сообществе спокойно сосуществуют и активно используются совершенно разные стили именования. В STL и Boost-е, как мне кажется, традиционный C/C++ стиль. В Qt, wxWidgets и в POCO -- более привычный для Pascal/Delphi/VisualBasic/Java/C#. В библиотеке ACE вообще свой собственный, неповторимый стиль, заимствующий хорошие элементы как из snake_case, так и из CamelCase.

Мы же уже очень давно используем snake_case стиль, но с некоторыми очень важными дополнениями. В частности, у нас для имен типов используются суффикс _t. Например, у нас тип агента называется agent_t, а не agent. А тип сообщения называется message_t, а не message.

К суффиксу _t в мире C++, как мне думается, отношение довольно своеобразное. Давным-давно от суффикса _t стремились отказываться, т.к. это выглядело темным наследием plain old C. В C-шном коде суффикс _t давали, как правило, именам typedef-ов. Например, писали что-то вроде typedef struct my_type {...} my_type_t;.

Но в последние годы, после выхода C++11 и, особенно, после выхода C++14, суффикс _t в C++ опять возвращается, но уже в специфической роли. Например, начиная с C++14 в стандарт языка добавляются сокращенные определения, вроде enable_if_t<C,T> вместо enable_if<C,T>::type. Так что теперь в C++ для суффикса _t появляется вполне определенная нише. И использование данного суффикса для других целей способно запутать стороннего разработчика (разорвать шаблон, так сказать).

Чтобы быть "ближе к народу", мы у себя попробовали провести небольшой натурный эксперимент. И для одной своей новой разработки попробовали отказаться от _t в пользу традиционного для STL/Boost стиля именования сущностей.

Результат нам не понравился. И если при написании кода отсутствие суффикса _t хоть и мешает, но приспособиться можно, то вот при чтении кода имена типов без привычного уже суффикса _t крайне тяжело выделять из кода. Так что читать чужой код написанный в стиле STL/Boost значительно тяжелее, чем код в нашей привычной нотации. Посему эксперимент был признан неудачным, код мы вернули к старому оформлению. Причем решение вернуться назад мы приняли намного легче, чем решение провести этот самый эксперимент :)

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

PS. Если бы мне сейчас предстояло выбирать нотацию для C++ного кода, я бы взял уже привычную нотацию со snake_case, с использованием префиксов m_ для полей структур/классов и g_ для глобальных переменных. А вот для пространств имен и имен типов сделал бы небольшое изменение: первая буква в таких именах должна была бы быть заглавной. Получилось бы что-то вроде So_5::Impl::Simple_mtsafe_st_env_infrastructure_details::Actual_elapsed_timers_collector вместо текущего so_5::impl::simple_mtsafe_st_env_infrastructure_details::actual_elapsed_timers_collector_t (имена, кстати говоря, реальные).

понедельник, 12 сентября 2016 г.

[prog.flame] Теплая ламповая сишечка, говорили они...

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

int 
ub_ctx_add_ta(struct ub_ctx* ctx, const char* ta)
{
   char* dup = strdup(ta);
   if(!dup) return UB_NOMEM;
   lock_basic_lock(&ctx->cfglock);
   if(ctx->finalized) {
      lock_basic_unlock(&ctx->cfglock);
      free(dup);
      return UB_AFTERFINAL;
   }
   if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_list, dup)) {
      lock_basic_unlock(&ctx->cfglock);
      free(dup);
      return UB_NOMEM;
   }
   lock_basic_unlock(&ctx->cfglock);
   return UB_NOERROR;
}

Классно, не правда ли? Прилежанию автора можно только позавидовать.

А потом настучать по рукам. За то, что не использует хотя бы идиому goto cleanup. Если уж перейти на C++ ума не хватило.

Если вам кажется, что это что-то из ряда вон, то это вы еще не видели следующей функции, которая в коде идет прямо вслед за только что показанной:

вторник, 26 июля 2016 г.

[prog.c++14] Упрощение себе жизни за счет возможностей современного C++. На примере работы с сокетами

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

Временами при работе с сокетами нужно устанавливать те или иные опции. Если нужно просто дергать setsockopt, то в этом нет ничего сложного. Хотя, если нужно дернуть setsockopt много раз подряд для установки разных опций, то тиражирование простого кода методом копипасты наверняка приведет к тому, что где-то будут перепутаны значения level и optname.

Еще же веселее ситуация становится, когда кроме setsockopt приходится работать с msghdr, sendmsg и recvmsg. Тут мы быстро приходим к простому коду вида:

for (cm = CMSG_FIRSTHDR (&msg); cm; cm = CMSG_NXTHDR (&msg, cm)) {
   void *ptr = CMSG_DATA (cm);

   if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SO_TIMESTAMP) {
         struct timeval *tv = (struct timeval *) ptr;
         ... // bla-bla-bla
      }
   }
   else if (cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_RECVERR) {
         struct sock_extended_err * ee = (struct sock_extended_err *) ptr;
         ... // bla-bla-bla
      }
   }
   else if (...)
      ...
}

Код-то простой. Но, как мне представляется, писать и сопровождать его готовы люди, которые не боятся сложностей. Я, например, боюсь :)

Тут ведь есть не только грабли с постоянными проверками cmsg_type и cmsg_level. Гораздо веселее -- это расчет размера буфера, который нужен для приема cmsghdr структур. Тут совсем несложно заблудиться в трех соснах. Например, взять опцию SOL_SOCKET/SO_TIMESTAMP. При вызове setsockopt для ее установки нужно задействовать int, который будет работать как bool. А при расчете размера cmsghdr нужно отводить место под timeval. При этом не забывая еще и про CMSG_LEN.

В общем, колупаться с такими подробностями в стиле plain old C -- это то еще удовольствие, как по мне. Поэтому...

четверг, 17 марта 2016 г.

[prog.flame] Программисты-сишники явно намного более трудолюбивы, чем я...

Ну вот взять ув.тов.asfikon-а (он же Eax Melanhovich) и его свежий пост про работу с libcurl из C (вот целиком исходный файл, о котором пойдет речь). Хватило же у человека терпения и прилежания тщательно выписывать очистку ресурсов при обнаружении ошибок в работе с libcurl:

CURLcode res = curl_easy_perform(curl);
if(res != CURLE_OK)
{
    fprintf(stderr"curl_easy_perform() failed: %s\n",
      curl_easy_strerror(res));
    writeFuncCtxFree(&ctx);
    curl_formfree(formFirstItem);
    curl_slist_free_all(curlHeaders);
    curl_easy_cleanup(curl);
    return 1;
}

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

curl_easy_setopt(curl, CURLOPT_URL, "http://imageshack.us/upload_api.php");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ctx);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curlHeaders);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formFirstItem);

Поначалу может казаться, что тут все тривиально и ошибкам возникать неоткуда... Но откуда только что берется со временем ;)

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

И не очень понятно почему так.

Сам я очень давно убедился в том, что не смогу нормально писать в таком стиле. Годах в 1991-1992-ом, когда более-менее серьезно попрограммировал на Pascal и C. Не хватает у меня терпения и внимательности для того, чтобы следить за тем количеством деталей, за которым приходится следить в C. Потому и ушел на C++ как только разобрался, что к чему.

А пример работы с libcurl хорош тем, что он иллюстрирует количество вещей, за которыми нужно следить при работе с C-шным API libcurl-а. Поэтому лет шесть назад, когда довелось втягивать libcurl в тогдашние проекты, дабы не заниматься всей этой низкоуровневой кухней, была написана простенькая C++ная библиотека, практически header-only. Под катом код примера из состава этой библиотеки.

суббота, 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-е код является тому подтверждением...

вторник, 26 мая 2015 г.

[prog.flame] Любопытная презентация про использование Java в авиации

В связи с 20-летием Java захотелось поискать примеров использования Java в софтовой начинке для самолетов. Наткнулся на slideshare.net вот на эту презентацию:

Любопытные ощущения :)

понедельник, 2 марта 2015 г.

[prog.flame] И вот в этом случае реализация акторов для C/C++ "ненужно"? ;)

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

Вот, например, две свежие темы с LOR-а от одного и того же автора: "Подскажите аналог GLUT, но без проблем с потоками" и "И таки как правильно потоки убивать?"

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

Да, при отсутствии агентов, да еще в чистом C, все это большой и нудный трах с pthreads.

Зато при наличии агентов и специального диспетчера, который может запускать агентов, в том числе, и на главной нити, все оказывается намного, очень намного проще и удобнее. В SObjectizer-4 мы такое проделывали и на голом WinAPI, и в Qt. Получалось просто и удобно.

В SObjectizer-5 пока такой надобности не было. Но, при необходимости, диспетчер главной рабочей нити, заточенный под какой-нибудь вменяемый GUI-фреймворк вполне можно сделать.

воскресенье, 21 сентября 2014 г.

[prog.c++] Предопределенные макросы компилятора

Наткнулся в Интернете на несколько статей, посвященных предопределенным макросам С++ компиляторов. Интересно и полезно:

C/C++ tip: How to list compiler predefined macros. Наборы аргументов командной строки для нескольких компиляторов, которые заставляют компилятор выдать список предопределенных макросов.

C/C++ tip: How to detect the operating system type using compiler predefined macros. Макросы компилятора, которые позволяют определить ОС.

C/C++ tip: How to detect the processor type using compiler predefined macros. Макросы компилятора, которые позволяют определить тип процессора.

Pre-defined Compiler Macros. Проект на SourceForge, который собирает информацию, аналогичную трем приведенным выше статьям.

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

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

[prog.c] Может быть кому-то пригодится: Concurrency Kit

Наткнулся на днях на Concurrency Kit. Позиционируют себя как "Concurrency primitives, safe memory reclamation mechanisms and non-blocking data structures for the research, design and implementation of high performance concurrent systems." Краткий список того, что предоставляет библиотека: "atomic operations, hardware transactional memory, memory barriers, hash tables, list, ring, stack, fifo, bitmap, safe memory reclamation, scalable locks, execution barriers, asymmetric synchronization and more."

Чистый C. Похоже, что поддерживаются только Unix-ы, без Windows и Visual C++. Лицензия BSD.

Сам глубоко не смотрел, не качал, не запускал. Но в свой склерозник внес.

пятница, 17 января 2014 г.

[prog.c++] Несколько ссылок на тему lock-free

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

libcds: http://libcds.sourceforge.net/

liblfds: http://liblfds.org/

Boost.Lockfree: http://www.boost.org/doc/libs/1_55_0/doc/html/lockfree.html

Concurent Building Blocks: http://amino-cbbs.sourceforge.net/

FastFlow: http://calvados.di.unipi.it/dokuwiki/doku.php?id=ffnamespace:about#fastflow_v2.0

DKit: https://github.com/drbobbeaty/DKit

sim-synch: https://code.google.com/p/sim-universal-construction/

Upd. Concurrency Kit: http://concurrencykit.org/. Чисто С-шная библиотека под BSD-лицензией и реализацией кучи всякой всячены (atomic operations, hardware transactional memory, memory barriers, hash tables, list, ring, stack, fifo, bitmap, safe memory reclamation, scalable locks, execution barriers, asymmetric synchronization). Похоже, что не поддерживает Windows и Visual C++.

Каталог разной полезной информации: http://www.1024cores.net/home/lock-free-algorithms/links (вообще сайт Дмитрия Вьюкова 1024cores настоятельно рекомендую).

Каталог разной полезной информации: http://yinsochen.com/thread-safe-and-or-lockless-data-structures/

Подборка статей на тему низкоуровневого многопоточного программирования: http://locklessinc.com/articles/

понедельник, 4 ноября 2013 г.

[prog.c++] В интересном порядке попались на глаза ссылки

На днях в интересном порядке попалось на глаза несколько ссылок, касающихся тонкостей C++ (и C).

Сначала это была презентация Deep C (and C++) (о которой я уже писал года полтора назад).

А затем ссылки на три записи в блоге LLVM, касательно оптимизации кода и взаимного влияние на это такой штуки, как undefined behaviour: What Every C Programmer Should Know About Undefined Behavior: #1, #2, #3 (ссылки были найдены здесь).

Интересное чтиво. Для действующих С++ (и C) разработчиков к прочтению обязательно, имхо.

Так же захотелось взять за правило бить по рукам тех, кто слишком много знает про особенности компиляторов и полагается в своем коде на тонкости стандарта. Чем проще и однозначнее код, тем меньше геморроя будущим поколениям. Хотя, конечно, полезно знать, чем отличается инициализация статической локальной переменной от автоматической. Но все же лучше, когда человек явно пишет static int i = 0, чем static int i. А еще лучше, когда статические переменные вообще не используются ;)

суббота, 3 августа 2013 г.

[prog.c] Оказывается WIN64 подразумевает наличие WIN32

Как-то внезапно для себя обнаружил, что предопределенный макрос _WIN64 подразумевает, что будет так же определен макрос _WIN32. Это если про Visual C++ говорить. В случае же с MinGW, аналогично, определенность __WIN64__ подразумевает определенность __WIN32__.

На первый взгляд выглядит странно. Хотя именно из-за такого поведения часть моего старого кода, обрабатывавшего макросы _WIN32 и __WIN32__ для задействования Windows-specific фрагментов, совершенно незаметно пережила переезд с 32-х на 64-е бита.

вторник, 19 июня 2012 г.

[prog.c] В догонку к Deep C (and C++)

…хотя зачастую на C/C++ нельзя написать нормальный код, если не иметь точных знаний на счет некоторых моментов. Совсем свежий пример, с пылу, с жару. Что не так в этом коде:

if(-1 == strcmp(a, b))…

[prog.c] Презентация Deep C (and C++)

Случайно наткнулся на блог норвежского разработчика Olve Maudal, а в нем на презентацию Deep C (and C++).

Интересно, очень познавательно.

Хотя лично я предпочту работать с людьми, которые не имеют столь глубоких знаний в C/C++ и, поэтому, будут писать так, чтобы только из кода было понятно, что и как работает. Как только в дело вступает глубокое знание тонких деталей стандарта или (что хуже) особенностей конкретных сред/компиляторов, тут нужно начинать бить по рукам. Если только не приходится каждый бит/такт экономить.

четверг, 23 декабря 2010 г.

[prog.wow] Реализация от Дмитрия Вьюкова заняла первое место в конкурсе WideFinder!

Несколько лет назад Тим Брей организовал свой собственный бенчмарк на одной простенькой задачке – парсинге большого объема лог-файлов на многопроцессорной машине. И назвал это соревнование WideFinder.

Долгое время этот бенчмарк использовался в спорах функциональщиков со всем остальным миром как доказательство преимущества ФП в написании быстрых и которых программ. Поскольку на первых местах в начале были реализации на OCaml от Маурисио Фернандеза. Но потом подтянулись C++ники и всех порвали (по крайней мере по скорости работы) :)

А потом пришел Дмитрий Вьюков (aka remark) и порвал вааще всех, включая C++ников :) На чистом C ;)

Текущую таблицу результатов (со ссылками на исходники всех реализаций) можно посмотреть здесь: http://wikis.sun.com/display/WideFinder/Results

А вот как выглядит ее верхняя часть сейчас (Smart-Finder – это и есть вариант Димы):

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