Так мы ж сверху договорились, что порядок величины не важен. Ну в два раза медленнее из-за проверок, подумаешь.
Дело не в этом. Дело в том, что есть некая базовая(самая примитивная) и единственно возможная имплементация — она написана на условном С++, императивно. Т.е. она примитивна и убога — её может повторить кто угодно, вот все и занимаются эти.
И смысл олимпиады в том, что попытаться выпилить из своего языка тонны оверхеда и проблем, которые не дают написать аналогичный условному С++ код. А то, что у кого-то там на копейку меньше, а у кого-то больше — это мало что меняет.
Смысл тут в том, что быстрее вы уже не сделаете. А вот питонист может сделать и мы не может у него это право забрать. Поэтому мы уславливаемся, что если все решения ± равны — они равны.
Чем отняли-то?
Ну как чем — задачей, которая является каноничным антипаттерном для всего, что связано с оптимизацией. Везде и во всём.
Так по дефолту пишется с Array, в чём вопрос-то тогда?
Ну почему тогда в хаскеле дефолт не array?
Лол. Когда удобно — просто баги, ничего не меняют, и то, что думать надо, тоже не меняют.
Нет, никаких удобно нет. Вы там сказали про «запутался в условиях», «перепутал, что массивы индексируются не с 1» — ничего из это не связано с оптимизацией, победами над каким-то там С++ и его идиомами — там нет.
Когда неудобно — мне рассказывают, как у меня происходил мыслительный процесс, когда я писал код.
Нет, разговор был не об этом.
Почему тогда в языках с одной имплементацией и без репорта вообще даже такого нет?
Какие языки? Вон раст — там есть. Такая же помойкаполигон. Везде и всюду.
Да, мы сейчас про PyPy вспомним, конечно. Ну давайте ещё повспоминаем про Hugs, Frege, ещё там какой-то хаскель под JVM был кроме него, да мало ли их.
Я не понял что это значит. Это совсем какие-то нонеймы. Очевидно, что если язык какая-то совсем дремучая маргинальная мертвечина, то там ничего не будет вне зависимости от есть/нет больше одно имплементации.
Почему?
Почему что?
Кстати, используемая денотационная семантика что для IntMap, что для Array тут одинаковая. Используемый синтаксис тоже одинаковый — формируем ленивый список как управляющую структуру данных и сворачиваем его. Всё. Канонично. Идиоматично.
Это попытка натянуть сову на глобус. Эта хрен генерирует индекс + значение, а вся неудобная магия происходит в кишках. Это по-сути та самая мутабельная хешмапа.
То есть, я правильно понимаю, что алгоритм плохой, потому что С++ на нём не сияет?
Нет. Не сияет здесь никто. Я уже приводил вполне понятную аналогию. К тому же, вы признаёте, что взяли по-сути подложный алгоритм, по-сути очередной факториал? Т.е. по-сути вы на старте отрубили ноги оппоненту и громогласно заявили о ничьей. Ну сильно, сильно.
К тому же, нету такого алгоритма в котором С++ не будет сиять. Именно поэтому я говорю о важности всех этих понятий «Канонично. Идиоматично.». Ведь именно на это поле вы сможете ответить С++, ведь если вы в каком-то алгоритме будете успешны, то С++ без проблем повторит и обойдёт ваш успех. Это битва не имеет смысла. Но, С++ будет вынужден использовать ваш подход. И именно это для вас должно быть важно.
И всё это каноничные вещи.
Постфактум можно назвать каноничным всё, что угодно. Хорошо, я не против.
А искать не пришлось.
Это неважно.
В чистом ФП нет reference'ов.
Их нет на уровне абстракций, но матчасть абстракции очередного языка мало интересует.
И это тоже не так. В ленивом языке у вас за термом типа Int в рантайме может лежать охренительный санк на стопицот вычислений. Который, если Int вам не нужен, можно подобрать GC.
Это всё элементарные вещи. В любом языке у вас за объектом может лежать стопицот чего угодно.
А, мы таки точно на императивщину переключились, причём на какой-то микс из C++ и непонятно чего. Ну ок.
Нет, мы переключились на матчасть. Так уж получилось, что железяка императивна, как и рантайм любого языка.
Массив — это просто структура данных с определённой семантикой и определёнными гарантиями производительности. GC тут ортогонален.
Нет. Вы же сами свой тезис в статье и опровергли. Именно потому, что ваш массив обладает правильной семантикой, которую описал я — вы что-то получили. Не обладай он этим, а обладай вашими определениями — этой статьи бы не было.
Я не знаю, как ещё написать, что это пример заведомо неэффективного кода, который писать не надо, и это очевидно сразу, заранее?
Я не говорю про алгоритмическую часть и про то, что можно посчитать(алгоритмически) проще и быстрее. Я именно про конкретную имплементацию, вернее про то, что у этой задачи только одна имплементация и это проблема. Нету никакого манёвра, никаких возможностей что-то сделать.
Да что вы прицепились к пистону. Я не знаю питона и не могу вам точно сказать — можно или нет. Но раз в pypy есть jit — я уверен, что производительность он выдаст.
И варианты оптимизации выше нигде не обсуждались? Замена accumArray на unsafeAccumArray порядок времени выполнения тоже не меняет так-то.
Да не особо — тут нечего оптимизировать просто. Кто-то умеет в unsafe, у кого-то рантайм не такой тормозной.
В любом случае вся эта борьба — борьба хаскелей с жаваскриптами. У нас есть просто наивный код на С++ и далее идёт соревнование уровня «кто сможет в этом хелоуворлде показать меньший оверхед». Замечу, оверхед не меньший/равный С++, не меньшей/равный в целом, а просто в рамках это задачи.
У С/С++ по-сути отняли тут всё. Это нечестно.
Если она будет частью стандартного питона (а у питона есть стандарт или хотя бы report?) — да без проблем.
Но Clean я не знаю
Как и я.
Его можно убрать повышением абстракций
Всё можно убрать, особенно постфактум. Как и в питоне можно сделать супер-массивы. Но мы имеем что имеем.
>>А чего с базовым?
С того, что мы говорим про «идиоматичный код», а это такой код, который пишет пользователь любого языка по-дефолту.
А какая разница в производительности по сравнению со случаем без transparent hugepages?
Аналогичная показанной. Именно хаскелю нужен transparent hugepages.
Нет, не сразу. Я ж даже написал, что сделал две тупых ошибки сначала (сделал вектор длины n, а не n + 1, и в цикле условия были <, а не <=, потому что рука так привыкла, если делать ни о чём не думая).
Это просто баги — эти обстоятельства ничего не меняют.
Брать специальные либы не нужно и в этом случае: Data.Array является частью спецификации языка.
Ну языки с одной имплементацией являются помойкойполигоном, в котором есть всё. В этом нет ничего удивительного. Абсолютно неважно где эта либа находится — она по-сути взламывает язык, привнося в него что-то непривычное. Если пример с массивом для вас слишком спорный — замените массив на ансейф. Это не особо важно.
Одна из целей (которая была в заметке аж в двух местах указана) — не только посмотреть, насколько эффективно можно сделать, но и какой разрыв между наиболее эффективным и заведомо неэффективным вариантом. Будет разница в 10 раз, в 100 раз, в 10000 раз? Для меня самого это ценная информация в копилку опыта.
Я уже говорил по этому поводу- нинасколько. Данный пример нельзя «сделать» эффективно. В этом и проблема. Вы не сделали ваш код эффективным — просто вы не дали С++ сделать его эффективным.
Ну и, кстати, это вообще какой-то странный критерий, про то, как я пишу сразу. Это было бы имело смысл, если бы на языке писал бы только я.
Вполне очевидный критерий. Да, везде и всюду можно пытаться эмулировать некий условный си, но зачем? Проще написать на си. Но суть заключается в том, что в реальных задачах вы же не станете так писать и ситуация измениться, координально.
Вот я прям сидел подбирал примеры.
Ну почему же подбирали. Просто нашли удобный пример.
А вы что именно имеете в виду? Я имею boxed/unboxed-типы, потому что reference семантику в контексте ФП обсуждать совсем бессмысленно. Да и дальнейший контекст на это намекает.
reference имеет смысл обсуждать всегда. В ситуации с гц есть два варианта. Объект — это объект гц и это всегда reference, со всеми вытекающими. Либо это value-type.
Почему?
Очень просто. Обычные объекты — существуют в скоупе gc и управляется гц, со всеми вытекающими. Элемент массива — это именно value-type, т.е. gc им не владеет(и не управляет), он хранит в себе только значение(и ничего больше).
В общем случае гц должен пройтись по массиву, чтобы пометить указывающие из массива thunk'и как доступные.
Это неважно. Важно лишь то, что гц владеет скоупом, т.е. куском памяти, которой является массив.
Кстати, это ещё одна причина — почему массив не каноничный. Массив целиком и полностью противоречит концепции gc.
На нём я бы не остановился заведомо, см. выше.
Я не понял ответ. Если компилятор/хаскель смог — дальше бы идти не пришлось.
Люди привели уже тысячи примеров, я привёл жаваскрипт. Везде результаты одного и того же порядка. К тому же, люди писали(как и я) просто первое, что придёт в голову. Вы же занимались оптимизацией.
Вон, с Go интересные своей неконсистентностью результаты, например.
Вполне типичные результаты.
Питон работает на пару порядков медленнее.
Питон не имеет jit, а я говорил именно о jit+. К тому же, я уверен что эти «порядки» были просто наивным кодом. Если там взять либу с массивчиком(как сделали вы), прикрутить unsafe и какое-нибудь pypy с житом — результат будут другие, я уверен.
Они как минимум показывают нижнюю границу оверхеда от всей этой декларативщины.
Нет, это наивное допущение. Это лишь показывает существования таких алгоритмов, которые работают одинаково плохо ВЕЗДЕ, а декларативщина — это прост одно из этого множества «плохо».
Это примерно как взять человека без ног и с ногами, замотать в ковёр и заставить кататься. А после сказать, что мы получили «нижнюю границу оверхеда отсутствия ног». Нет. Вы выбрали такую игру, в которой забрали у человека с ногами его преимущество — его ноги. По-сути сделав его таким безногим.
За свободу приходится расплачиваться.
За всё приходится, свобода в этом плане не является чем-то уникальным.
Чуть большим объёмом кода
Кода на хаскеле больше.
чуть меньшей безопасностью, чуть меньшей дружественностью к рефакторингу, вот это всё.
Это всё правильно, но есть нюансы. Говорить об этом попросту нету смысла. Если зада требует производительности и масштаба — все эти рассуждения тут же теряют смысл.
Причина проста — все конкуренты тут же исчезаю и лоулевел мир остаётся сам с собою. И тут уже неважно насколько безопасен хаскель — он попросту выносится за скобки, т.к. применения не имеет.
На самом деле с transparent hugepage это не совсем обязательно.
Почему? ФП — это не про то, чтобы делать всё на одних списках.
Ну вот вы целую статью написали о том, как победили тысячи проблем. Вам бы не пришлось об этом писать, если бы проблем не было. Вы ведь на С++ написали код сразу, ни о чём не думая и ничего не меняя. Вот именно поэтому.
Data.Array — достаточно каноничная вещь
Вот смотрите. Вы берёте С/С++ и у вас там есть массив. Это база языка. Не нужно решать, делать специальные либы и решать тысячи проблем. Это называется канонично.
Если ещё проще. Канонично — это то, что вы пишете на языке сразу. И вы написали каноничный код на хаскеле в первом вашем примере, а далее попытались «написать как на си».
На самом деле это даже лишнее, но я уже не стал править статью — достаточно левую границу передвинуть с 1 на 0, и всё.
Это понятно, я говорил не об этом. Вы возмущались индексацией с нуля, а значит для вас подобное поведение не является привычным. Т.е. решение этой задачи «производительным» способом потребовало вас отказаться от «привычно».
Ну это ещё как-то можно притянуть, наверное, да. Хотя тогда и в C++ использование [] вместо .at() неидиоматично (или вы считаете идиоматичным потенциально опасный доступ?).
Да, считаю(и не только я). Именно поэтому at() там опция, а [] — дефолт. В этом опять же разница. Вам пришлось изменять своему видению, изменять видению языка и его базовой концепции. Именно это я и имел ввиду, когда приводил все эти примеры.
Действительно неидиоматичным кодом было бы засунуть всё в ST, или взять, например, ghc-primops и нафигачить параллелизм через ручное ковыряние атомиков, или написать всё руками с unboxed-версией инта (которая Int#).
Просто пример слишком просто и удачный. Вам не пришлось далеко уходить, но это просто хорошо подобранный пример. Причём, пример не особе адекватный реальному применению.
Но в хаскеле ghc нет jit,
Я написал это в контексте «как минимум».
>>и нет value-типов (если вы не начинаете брать #-типы, а их тут никто не брал).
Как так нету? А что такое ваш массив? Это именно value-тип.
Зато есть GC
Элемент массива неподвластен гц и является value-типом.
и тот факт, что компилятор может развернуть декларативный код
Неможет. В противном случае вы бы остановились на первом примере.
и это в каком-то смысле ответ на «да эта ваша функциональщина тормозит как не в себя»
Ещё раз, вы пытались доказать силу хаскеля и то, что он может не только в факториалы. Вы написали факториал и получили производительность жаваскрипта. Т.е. вы не сделали ни первого ни второго.
Скорее всего у вас старый гцц. И у вас очень странные результаты. Покажи результат: cat /sys/kernel/mm/transparent_hugepage/enabled — ядро должно само закатывать хотя-бы 2m страницами такие случаи.
Покритикую. Для затравочки: 62 sec //C++
119 sec //хаскель
Только факториалы и препроморфизмы на нём и писать! Или нет?
Только вот проблема — ваша задача такой же факториал.
Код по-прежнему идиоматичен.
Нет. «идиоматичен» там С++. Так можно что угодно назвать чем угодно, допустим, этот жс тоже «идиоматичен».
function f(n) {
let arr = new Int32Array(n + 1);
for(let k1 = 1; k1 <= Math.floor(Math.sqrt(n)); ++k1) {
for (let k2 = k1; k2 <= n / k1; ++k2) {
let val = k1 != k2 ? k1 + k2 : k1;
arr[k1 * k2] += val;
}
}
return arr;
}
Этот код, кстати, показывает результат почти такой же как и хаскель(с поправкой на 64битные инты). Правда, в жс нету 64 битных интов, но суть не в этом.
Очевидно, что код не является идиоматичным, когда существуют подобные допущения:
Почему бы нам не использовать массив
необходимости индексироваться с нуля
ленивость в нём нам не нужна.
Попробуем заменить вызов accumArray на unsafeAccumArray:
Думаю, можно сказать, что это победа.
Нет, это не победа. Наоборот — проигрыш. Что вы хотели показать этим примером? «хаскель может как С++», но вы показали не это. Вы показали «существуют такие примеры, которые везде работают хренова и хаскель тут очередной жс».
Да, существуют множество случаев, когда никакая оптимизация невозможна и случай прощает все(почти) недочёты «обычных» языков. Это один из них. Всё, что языку нужно для «показать производительность уровня си» — это value-типы, «массив» и jit. Это и было показано в теме. И подобные примеры все такие. Проблема только одна — такие случаи редки и это те самые факториалы. Они бесполезны, они ничего не показывают.
И самое важное. Сравнение языков — глупость. Нет никакого «быстрого С/С++». Есть люди, которые обладают знанием, пониманием и опытом. А С/С++ — это просто инструмент, который позволяет им этот всё применить на практике. И именно в этом случае что-то становится быстрым. И проблема хаскеля(и иже с ним) не в том, что они как-то плохо считают факториалы(хотя и это тоже. Ведь сколько вы потратили времени на обходные пути). Проблема в том, что они не дают той свободы и той возможности.
Поэтому, статьи на хабре с заголовками «очередной факториал на хаскеле не тормозит» — это хорошо, но мало что даёт. А вот затюнить ядро, чтобы исключить, если попроще, dtlb-промахи — это даёт х2.
Ну да, сравнить же нужно.
Ну хоть что-то.
Дело не в этом. Дело в том, что есть некая базовая(самая примитивная) и единственно возможная имплементация — она написана на условном С++, императивно. Т.е. она примитивна и убога — её может повторить кто угодно, вот все и занимаются эти.
И смысл олимпиады в том, что попытаться выпилить из своего языка тонны оверхеда и проблем, которые не дают написать аналогичный условному С++ код. А то, что у кого-то там на копейку меньше, а у кого-то больше — это мало что меняет.
Смысл тут в том, что быстрее вы уже не сделаете. А вот питонист может сделать и мы не может у него это право забрать. Поэтому мы уславливаемся, что если все решения ± равны — они равны.
Ну как чем — задачей, которая является каноничным антипаттерном для всего, что связано с оптимизацией. Везде и во всём.
Ну почему тогда в хаскеле дефолт не array?
Нет, никаких удобно нет. Вы там сказали про «запутался в условиях», «перепутал, что массивы индексируются не с 1» — ничего из это не связано с оптимизацией, победами над каким-то там С++ и его идиомами — там нет.
Нет, разговор был не об этом.
Какие языки? Вон раст — там есть. Такая же
помойкаполигон. Везде и всюду.Я не понял что это значит. Это совсем какие-то нонеймы. Очевидно, что если язык какая-то совсем дремучая маргинальная мертвечина, то там ничего не будет вне зависимости от есть/нет больше одно имплементации.
Почему что?
Это попытка натянуть сову на глобус. Эта хрен генерирует индекс + значение, а вся неудобная магия происходит в кишках. Это по-сути та самая мутабельная хешмапа.
Нет. Не сияет здесь никто. Я уже приводил вполне понятную аналогию. К тому же, вы признаёте, что взяли по-сути подложный алгоритм, по-сути очередной факториал? Т.е. по-сути вы на старте отрубили ноги оппоненту и громогласно заявили о ничьей. Ну сильно, сильно.
К тому же, нету такого алгоритма в котором С++ не будет сиять. Именно поэтому я говорю о важности всех этих понятий «Канонично. Идиоматично.». Ведь именно на это поле вы сможете ответить С++, ведь если вы в каком-то алгоритме будете успешны, то С++ без проблем повторит и обойдёт ваш успех. Это битва не имеет смысла. Но, С++ будет вынужден использовать ваш подход. И именно это для вас должно быть важно.
Постфактум можно назвать каноничным всё, что угодно. Хорошо, я не против.
Это неважно.
Их нет на уровне абстракций, но матчасть абстракции очередного языка мало интересует.
Это всё элементарные вещи. В любом языке у вас за объектом может лежать стопицот чего угодно.
Нет, мы переключились на матчасть. Так уж получилось, что железяка императивна, как и рантайм любого языка.
Нет. Вы же сами свой тезис в статье и опровергли. Именно потому, что ваш массив обладает правильной семантикой, которую описал я — вы что-то получили. Не обладай он этим, а обладай вашими определениями — этой статьи бы не было.
Я не говорю про алгоритмическую часть и про то, что можно посчитать(алгоритмически) проще и быстрее. Я именно про конкретную имплементацию, вернее про то, что у этой задачи только одна имплементация и это проблема. Нету никакого манёвра, никаких возможностей что-то сделать.
Да что вы прицепились к пистону. Я не знаю питона и не могу вам точно сказать — можно или нет. Но раз в pypy есть jit — я уверен, что производительность он выдаст.
Да не особо — тут нечего оптимизировать просто. Кто-то умеет в unsafe, у кого-то рантайм не такой тормозной.
В любом случае вся эта борьба — борьба хаскелей с жаваскриптами. У нас есть просто наивный код на С++ и далее идёт соревнование уровня «кто сможет в этом хелоуворлде показать меньший оверхед». Замечу, оверхед не меньший/равный С++, не меньшей/равный в целом, а просто в рамках это задачи.
У С/С++ по-сути отняли тут всё. Это нечестно.
Как и я.
Всё можно убрать, особенно постфактум. Как и в питоне можно сделать супер-массивы. Но мы имеем что имеем.
С того, что мы говорим про «идиоматичный код», а это такой код, который пишет пользователь любого языка по-дефолту.
Аналогичная показанной. Именно хаскелю нужен transparent hugepages.
Это просто баги — эти обстоятельства ничего не меняют.
Ну языки с одной имплементацией являются
помойкойполигоном, в котором есть всё. В этом нет ничего удивительного. Абсолютно неважно где эта либа находится — она по-сути взламывает язык, привнося в него что-то непривычное. Если пример с массивом для вас слишком спорный — замените массив на ансейф. Это не особо важно.Я уже говорил по этому поводу- нинасколько. Данный пример нельзя «сделать» эффективно. В этом и проблема. Вы не сделали ваш код эффективным — просто вы не дали С++ сделать его эффективным.
Вполне очевидный критерий. Да, везде и всюду можно пытаться эмулировать некий условный си, но зачем? Проще написать на си. Но суть заключается в том, что в реальных задачах вы же не станете так писать и ситуация измениться, координально.
Ну почему же подбирали. Просто нашли удобный пример.
reference имеет смысл обсуждать всегда. В ситуации с гц есть два варианта. Объект — это объект гц и это всегда reference, со всеми вытекающими. Либо это value-type.
Очень просто. Обычные объекты — существуют в скоупе gc и управляется гц, со всеми вытекающими. Элемент массива — это именно value-type, т.е. gc им не владеет(и не управляет), он хранит в себе только значение(и ничего больше).
Это неважно. Важно лишь то, что гц владеет скоупом, т.е. куском памяти, которой является массив.
Кстати, это ещё одна причина — почему массив не каноничный. Массив целиком и полностью противоречит концепции gc.
Я не понял ответ. Если компилятор/хаскель смог — дальше бы идти не пришлось.
Люди привели уже тысячи примеров, я привёл жаваскрипт. Везде результаты одного и того же порядка. К тому же, люди писали(как и я) просто первое, что придёт в голову. Вы же занимались оптимизацией.
Вполне типичные результаты.
Питон не имеет jit, а я говорил именно о jit+. К тому же, я уверен что эти «порядки» были просто наивным кодом. Если там взять либу с массивчиком(как сделали вы), прикрутить unsafe и какое-нибудь pypy с житом — результат будут другие, я уверен.
Да, особенно по строкам:
Здесь меньше строк и во много раз меньше синтаксического мусора.
А о чём же? Любой unsafe это по определению лоулевел. Как минимум относительно абстракций. Любая производительность — лоулевел.
Нет, это наивное допущение. Это лишь показывает существования таких алгоритмов, которые работают одинаково плохо ВЕЗДЕ, а декларативщина — это прост одно из этого множества «плохо».
Это примерно как взять человека без ног и с ногами, замотать в ковёр и заставить кататься. А после сказать, что мы получили «нижнюю границу оверхеда отсутствия ног». Нет. Вы выбрали такую игру, в которой забрали у человека с ногами его преимущество — его ноги. По-сути сделав его таким безногим.
За всё приходится, свобода в этом плане не является чем-то уникальным.
Кода на хаскеле больше.
Это всё правильно, но есть нюансы. Говорить об этом попросту нету смысла. Если зада требует производительности и масштаба — все эти рассуждения тут же теряют смысл.
Причина проста — все конкуренты тут же исчезаю и лоулевел мир остаётся сам с собою. И тут уже неважно насколько безопасен хаскель — он попросту выносится за скобки, т.к. применения не имеет.
Базовым вашим.
Я только аллокатор на нормальный поменял:
На самом деле с transparent hugepage это не совсем обязательно.
Ну вот вы целую статью написали о том, как победили тысячи проблем. Вам бы не пришлось об этом писать, если бы проблем не было. Вы ведь на С++ написали код сразу, ни о чём не думая и ничего не меняя. Вот именно поэтому.
Вот смотрите. Вы берёте С/С++ и у вас там есть массив. Это база языка. Не нужно решать, делать специальные либы и решать тысячи проблем. Это называется канонично.
Если ещё проще. Канонично — это то, что вы пишете на языке сразу. И вы написали каноничный код на хаскеле в первом вашем примере, а далее попытались «написать как на си».
Это понятно, я говорил не об этом. Вы возмущались индексацией с нуля, а значит для вас подобное поведение не является привычным. Т.е. решение этой задачи «производительным» способом потребовало вас отказаться от «привычно».
Да, считаю(и не только я). Именно поэтому at() там опция, а [] — дефолт. В этом опять же разница. Вам пришлось изменять своему видению, изменять видению языка и его базовой концепции. Именно это я и имел ввиду, когда приводил все эти примеры.
Просто пример слишком просто и удачный. Вам не пришлось далеко уходить, но это просто хорошо подобранный пример. Причём, пример не особе адекватный реальному применению.
Я написал это в контексте «как минимум».
>>и нет value-типов (если вы не начинаете брать #-типы, а их тут никто не брал).
Как так нету? А что такое ваш массив? Это именно value-тип.
Элемент массива неподвластен гц и является value-типом.
Неможет. В противном случае вы бы остановились на первом примере.
Ещё раз, вы пытались доказать силу хаскеля и то, что он может не только в факториалы. Вы написали факториал и получили производительность жаваскрипта. Т.е. вы не сделали ни первого ни второго.
Это плохо, нужно включить в ядре:
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
62 sec //C++
119 sec //хаскель
Только вот проблема — ваша задача такой же факториал.
Нет. «идиоматичен» там С++. Так можно что угодно назвать чем угодно, допустим, этот жс тоже «идиоматичен».
Этот код, кстати, показывает результат почти такой же как и хаскель(с поправкой на 64битные инты). Правда, в жс нету 64 битных интов, но суть не в этом.
Очевидно, что код не является идиоматичным, когда существуют подобные допущения:
Нет, это не победа. Наоборот — проигрыш. Что вы хотели показать этим примером? «хаскель может как С++», но вы показали не это. Вы показали «существуют такие примеры, которые везде работают хренова и хаскель тут очередной жс».
Да, существуют множество случаев, когда никакая оптимизация невозможна и случай прощает все(почти) недочёты «обычных» языков. Это один из них. Всё, что языку нужно для «показать производительность уровня си» — это value-типы, «массив» и jit. Это и было показано в теме. И подобные примеры все такие. Проблема только одна — такие случаи редки и это те самые факториалы. Они бесполезны, они ничего не показывают.
И самое важное. Сравнение языков — глупость. Нет никакого «быстрого С/С++». Есть люди, которые обладают знанием, пониманием и опытом. А С/С++ — это просто инструмент, который позволяет им этот всё применить на практике. И именно в этом случае что-то становится быстрым. И проблема хаскеля(и иже с ним) не в том, что они как-то плохо считают факториалы(хотя и это тоже. Ведь сколько вы потратили времени на обходные пути). Проблема в том, что они не дают той свободы и той возможности.
Поэтому, статьи на хабре с заголовками «очередной факториал на хаскеле не тормозит» — это хорошо, но мало что даёт. А вот затюнить ядро, чтобы исключить, если попроще, dtlb-промахи — это даёт х2.