После выхода второго номера журнала "Практика функционального программирования" у меня состоялась интересная переписка с неким программистом, который очень любит писать на C.
Кульминацией этой переписки стало то, что он предложил мне следующее пари: я формулирую простенькую задачу, после чего мы оба реализуем ее - он на С, я - на Haskell. После этого в условие вносятся небольшие коррективы (моделируем поведение требований в реальном мире), а мы вносим коррективы в наши программы. Результаты сравниваются по скорости исполнения, объему потребляемой памяти, количеству строк кода.
Мой оппонент изначально был поставлен в неравные условия, т.к. я мог подобрать задачу так, чтобы ее было удобно реализовывать мне, и неудобно реализовывать ему. Впрочем, я постарался выбрать задачу так, чтобы ее решение не требовало каких-то узкоспециальных знаний. Фактически, мы занимались тем, что читали из файла и обрабатывали некую сложную структуру данных. (Детальное условие я тут не привожу, чтобы не "сбивать прицел" второй половине поста).
Моя первая версия активно использовала Data.Generics и библиотечные парсеры на их основе, поэтому выиграла в размере и читаемости кода, но пролетела по объему потребляемой памяти. Впрочем, мой оппонент настолько понадеялся на мощь C, что решил не использовать библиотечный qsort, а реализовать insertion sort самостоятельно. Это самым пагубным образом сказалось на производительности (LOCs - строки кода, память - в мегабайтах, время - в секундах):
Кроме того, выяснилось, что мой оппонент всячески "срезает углы" в погоне за производительностью. Например, функция сохранения обработанных данных в файл принимала, в числе прочих, числовой параметр, на который умножались определенные поля структуры перед сохранением - таким образом экономился один рекурсивный обход всей структуры данных.
В результате я тоже решил "срезать углы", и принести красоту кода в жертву скорости. Мой же оппонент взялся за qsort, и к вторые (финальная) версии нашего кода "финишировали" с такими результатами:
Я предполагал, что соотношение цифр будет гораздо сильнее не в пользу Haskell. Впрочем, меня по-прежнему можно было бы обвинить в предвзятом подходе к формулированию условий.
К чему я все это веду?
Существует классическая статья "Haskell vs. Ada vs. C++ vs. Awk vs. ... An Experiment in Software Prototyping Productivity", написанная в 1994-м году. За 15 лет многое изменилось, и, думается, многим было бы интересно прочитать подобную статью про положение дел сегодня.
В связи с этим ищутся:
1)Условия подходящей задачи (критерии см. ниже)
2)Желающие реализовать ее на Haskell/C+/Ocaml/Java/Scala/C#/... с тем, чтобы ваш код был нещадно сравнен с другими и опубликован для всеобщего обозрения.
Q:Зачем все это делается?
A:На других посмотреть, себя показать. В частности, чтобы люди имели возможность посмотреть на решения на других языках, и составить о них какие-то мнение.
Q:Чем не устраивает The Great Language Shootout?
A:Тем, что там отдается предпочтение "быстрым и грязным" решениям, которые всячески "срезают углы". Во-первых, в таком стиле пишется дай бог чтобы 5% от всех программ, во-вторых, людям, не знающим язык X, строго противопоказано смотреть на решения на языке X в Language Shootout - останется превратное впечатление.
Q:Как будут сравниваться решения, чтобы определить победителя?
A:Никак, т.к. победителей не будет. Будут приведена определенная статистика по всем решениям, без выводов.
Q:Какой тогда стимул участвовать?
A:На других посмотреть, себя показать :)
Какой должна быть задача?
1)Не заточенной под конкретную ОС (т.е. "Реализовать компонент, встраеваемый в Word" или "плагин для libpam" - не катит)
2)Не заточенной под конкретный язык/фреймворк/... (т.е. "получить список сигнатур методов всех объектов указанной сборки .Net" - не катит)
3)Если глубокие знания в предметной области дают решающее преимущество - это fail (т.е. "реализовать DES-CBC" - не катит)
4)Чтобы она не была из категории "мне не нужно, чтобы плац был чистый, а нужно, чтобы вы задолбались" (т.е. "распарсить XLS-файл, не пользуясь библиотеками" - не катит)
5)Задача не должна требовать много времени на реализацию (если это будут человеко-недели - никто за нее не возьмется)
Какой должна быть реализация?
1)Чтобы ее было не стыдно показать другим. В частности, чтобы решение на языке X не заплевали бы как кривое и неидиоматичное другие программисты, знающие язык X.
2)Идеально было бы давать две реализации: первую с ориентиром на "красоту", "образцово-показательность" и легкость поддержки/развития кода (т.е. пишем как пример кода, который будет прилагаться к резюме :), а вторую - "грязную и быструю".
3)Т.к. библиотеки - это неотъемлимая часть силы и популярности языка, библиотеками "общего назначения" (контейнеры, парсинг, ...) пользоваться можно и нужно
4)Но! Решение, которое свелось к исключительно к нахождению и использованию какой-то (узкоспециальной) библиотеки никому не интересно и рассматриваться не будет.
Выбирать подходящее условие будет жюри, представляющее апологетов всех течений и направлений, в том числе - включающее тех, кто критически отзывался о материалах, уже вышедших в fprog.ru.
Если у вас есть идея подходящией задачи и вы хотите ей поделится - напишите комментарий, а?
Кульминацией этой переписки стало то, что он предложил мне следующее пари: я формулирую простенькую задачу, после чего мы оба реализуем ее - он на С, я - на Haskell. После этого в условие вносятся небольшие коррективы (моделируем поведение требований в реальном мире), а мы вносим коррективы в наши программы. Результаты сравниваются по скорости исполнения, объему потребляемой памяти, количеству строк кода.
Мой оппонент изначально был поставлен в неравные условия, т.к. я мог подобрать задачу так, чтобы ее было удобно реализовывать мне, и неудобно реализовывать ему. Впрочем, я постарался выбрать задачу так, чтобы ее решение не требовало каких-то узкоспециальных знаний. Фактически, мы занимались тем, что читали из файла и обрабатывали некую сложную структуру данных. (Детальное условие я тут не привожу, чтобы не "сбивать прицел" второй половине поста).
Моя первая версия активно использовала Data.Generics и библиотечные парсеры на их основе, поэтому выиграла в размере и читаемости кода, но пролетела по объему потребляемой памяти. Впрочем, мой оппонент настолько понадеялся на мощь C, что решил не использовать библиотечный qsort, а реализовать insertion sort самостоятельно. Это самым пагубным образом сказалось на производительности (LOCs - строки кода, память - в мегабайтах, время - в секундах):
| LOCs | MEM max | Runtime, sec | |
| Haskell, v1 | 72 | 580 | 88 |
| C++, v1 | 861 | 55 | 383 |
Кроме того, выяснилось, что мой оппонент всячески "срезает углы" в погоне за производительностью. Например, функция сохранения обработанных данных в файл принимала, в числе прочих, числовой параметр, на который умножались определенные поля структуры перед сохранением - таким образом экономился один рекурсивный обход всей структуры данных.
В результате я тоже решил "срезать углы", и принести красоту кода в жертву скорости. Мой же оппонент взялся за qsort, и к вторые (финальная) версии нашего кода "финишировали" с такими результатами:
| LOCs | MEM max | Runtime, sec | |
| Haskell, v2 | 169 | 130 | 8 |
| C++, v2 | 950 | 54 | 5 |
Я предполагал, что соотношение цифр будет гораздо сильнее не в пользу Haskell. Впрочем, меня по-прежнему можно было бы обвинить в предвзятом подходе к формулированию условий.
К чему я все это веду?
Существует классическая статья "Haskell vs. Ada vs. C++ vs. Awk vs. ... An Experiment in Software Prototyping Productivity", написанная в 1994-м году. За 15 лет многое изменилось, и, думается, многим было бы интересно прочитать подобную статью про положение дел сегодня.
В связи с этим ищутся:
1)Условия подходящей задачи (критерии см. ниже)
2)Желающие реализовать ее на Haskell/C+/Ocaml/Java/Scala/C#/... с тем, чтобы ваш код был нещадно сравнен с другими и опубликован для всеобщего обозрения.
Q:Зачем все это делается?
A:На других посмотреть, себя показать. В частности, чтобы люди имели возможность посмотреть на решения на других языках, и составить о них какие-то мнение.
Q:Чем не устраивает The Great Language Shootout?
A:Тем, что там отдается предпочтение "быстрым и грязным" решениям, которые всячески "срезают углы". Во-первых, в таком стиле пишется дай бог чтобы 5% от всех программ, во-вторых, людям, не знающим язык X, строго противопоказано смотреть на решения на языке X в Language Shootout - останется превратное впечатление.
Q:Как будут сравниваться решения, чтобы определить победителя?
A:Никак, т.к. победителей не будет. Будут приведена определенная статистика по всем решениям, без выводов.
Q:Какой тогда стимул участвовать?
A:На других посмотреть, себя показать :)
Какой должна быть задача?
1)Не заточенной под конкретную ОС (т.е. "Реализовать компонент, встраеваемый в Word" или "плагин для libpam" - не катит)
2)Не заточенной под конкретный язык/фреймворк/... (т.е. "получить список сигнатур методов всех объектов указанной сборки .Net" - не катит)
3)Если глубокие знания в предметной области дают решающее преимущество - это fail (т.е. "реализовать DES-CBC" - не катит)
4)Чтобы она не была из категории "мне не нужно, чтобы плац был чистый, а нужно, чтобы вы задолбались" (т.е. "распарсить XLS-файл, не пользуясь библиотеками" - не катит)
5)Задача не должна требовать много времени на реализацию (если это будут человеко-недели - никто за нее не возьмется)
Какой должна быть реализация?
1)Чтобы ее было не стыдно показать другим. В частности, чтобы решение на языке X не заплевали бы как кривое и неидиоматичное другие программисты, знающие язык X.
2)Идеально было бы давать две реализации: первую с ориентиром на "красоту", "образцово-показательность" и легкость поддержки/развития кода (т.е. пишем как пример кода, который будет прилагаться к резюме :), а вторую - "грязную и быструю".
3)Т.к. библиотеки - это неотъемлимая часть силы и популярности языка, библиотеками "общего назначения" (контейнеры, парсинг, ...) пользоваться можно и нужно
4)Но! Решение, которое свелось к исключительно к нахождению и использованию какой-то (узкоспециальной) библиотеки никому не интересно и рассматриваться не будет.
Выбирать подходящее условие будет жюри, представляющее апологетов всех течений и направлений, в том числе - включающее тех, кто критически отзывался о материалах, уже вышедших в fprog.ru.
Если у вас есть идея подходящией задачи и вы хотите ей поделится - напишите комментарий, а?
(no subject)
Date: 2009-11-03 10:38 pm (UTC)(no subject)
Date: 2009-11-03 10:42 pm (UTC)(no subject)
Date: 2009-11-03 10:43 pm (UTC)(no subject)
Date: 2009-11-03 10:48 pm (UTC)Шутка. ;)
Рейтресеры.
Поиск пути в области со статическими и движущимися объектами, малой плотностью оных.
Двумерная игровая физика.
(no subject)
Date: 2009-11-03 10:48 pm (UTC)(no subject)
Date: 2009-11-03 10:50 pm (UTC)Для неё и программы писать легко (нет ограничений на длину ключа-контекста, значит, можно делать произвольную рекурсию) и (!) её очень интересно модифицировать.
(no subject)
Date: 2009-11-03 10:51 pm (UTC)(no subject)
Date: 2009-11-03 10:53 pm (UTC)А если чуть более серьёзно, то эта штука меряет только перформанс. А то что на хаскеле это будет одна строка, а на си — стопятьсот, это как-бы тоже должно быть измеряемым фактором в финальном решении. То есть, задаче желательно не состоять в том, что она замеряет перформанс и/или лаконичность сама собой. На это постмортем анализ есть: что короче, и насколько при этом быстрее (медленнее).
(no subject)
Date: 2009-11-03 10:58 pm (UTC)я сразу сказал, что меряли C vs C++, поэтому количество кода было одинаковым, вся заруба шла на то, что быстрее работает - файлы vs потоки, select vs virtual ну и дальше подобные мелочи
(no subject)
Date: 2009-11-03 11:02 pm (UTC)PS
А конечный авторма на Haskell/любом языке с patter matching - это с десяток строк
(no subject)
Date: 2009-11-03 11:02 pm (UTC)(no subject)
Date: 2009-11-03 11:03 pm (UTC)(no subject)
Date: 2009-11-03 11:08 pm (UTC)(no subject)
Date: 2009-11-03 11:12 pm (UTC)(Сейчас придет
(no subject)
Date: 2009-11-03 11:17 pm (UTC)(no subject)
Date: 2009-11-03 11:23 pm (UTC)(no subject)
Date: 2009-11-03 11:25 pm (UTC)Наверное, каждый, кто пишет на C/C++ профессионально, вынужден был в какой-то момент свой кастом мемори аллокатор написать.
В двадцать первом веке.
Тьфу.
(no subject)
Date: 2009-11-03 11:31 pm (UTC)http://www.cs.umass.edu/~emery/pubs/berger-oopsla2002.pdf
После этого, впрочем, был вынужден делать ДВА general-purpose аллокатора памяти для Cisco. Наверное, чужой опыт меня не убедил.
(no subject)
Date: 2009-11-03 11:33 pm (UTC)(no subject)
Date: 2009-11-03 11:37 pm (UTC)Только она другого уровня: не механическая (ещё класс, ещё темплейт, ещё один аллокатор), а математическая.
Ещё нужно учитывать, что большинство этих людей C/C++ знают очень даже на уровне, часто экспертном. Поэтому противопоставление хаскелистам сиплюсплюсных решений и аргументов забавно: аргументы из прошлой жизни. Ностальгия.
(no subject)
Date: 2009-11-03 11:42 pm (UTC)и радость мне доставляет изучение ассемблерных листингов скомпилированного кода и бюджеты за мою работу.
мы с вами думаем на разных языках.
(no subject)
Date: 2009-11-03 11:50 pm (UTC)Так что, опять же, все эти задачи я понимаю, знаю, и люблю.
... плюс теперь хаскель. Это позволяет лучше потом на си писать.
(no subject)
Date: 2009-11-03 11:56 pm (UTC)(no subject)
Date: 2009-11-03 11:58 pm (UTC)(no subject)
Date: 2009-11-04 12:07 am (UTC)Общий алгоритм сводится к "посмотреть на множество сообщений, выбрать готовое к выполнению, выполнить, добавить его результат в множество сообщений".