Привет.
На днях Siemargl предложил мне перевести любопытную статью о победе над юниксовым wc
при помощи хаскеля. Переводить её я, конечно же, не буду, и по нескольким причинам:
- автор выжал из однопоточной версии далеко не всё, и однопоточная версия была существенно медленнее
wc
,
- в той статье для победы потребовалось воспользоваться многопоточностью (что само по себе немного читерство и победа скорее над здравым смыслом, а не над
wc
),
- для этого автору пришлось углубляться в
трихомонады и моноиды — не, это отличная иллюстрация прелестей моноидального мышления, но ИМХО немного перебор для такой задачи, тем более, что из-за этого
- код получился излишне объёмным,
- да и вообще, соревноваться с
wc
, которая имеет кучу опций и фич, реализуя её ну очень игрушечный аналог, вообще как-то странно и даже немного глуповато.
Тем не менее, заниматься странными делами — дело хорошее, поэтому сегодня мы попробуем исправить первый из пунктов выше и улучшим результат Криса (так звать автора исходной статьи).
Опять же, как мы выяснили в прошлый раз, код на C я писать не умею, так что писать его и не буду, а в качестве конкурента хаскель-реализации у меня (как и у Криса) выступает сишный wc
из GNU Coreutils. Те чуваки уж точно на C писать умеют, коду этому не один десяток лет, да и о производительности они позаботились, судя по таким кусочкам:
/* If the average line length in the block is >= 15, then use
memchr for the next block, where system specific optimizations
may outweigh function call overhead.
FIXME: This line length was determined in 2015, on both
x86_64 and ppc64, but it's worth re-evaluating in future with
newer compilers, CPUs, or memchr() implementations etc. */
Спойлер: мы обгоним сишный wc
примерно на порядок без всяких проблем, получив вполне идиоматичный код и потратив менее получаса на изменения и оптимизацию оригинального кода.
Читать полностью »