Як наслідувати wc -l у Раку


9

У perl 5 ви можете імітувати wc -lза допомогою oneliner:

perl -lnE 'END {say $.}' test.txt

Як реалізувати цю функціональність на Raku

Якщо ви спробуєте реалізувати це:

raku -e 'say "test.txt".IO.open.lines.elems'

воно виявляється повільним і використовує багато пам’яті

Інформація для відтворення:

$ wget http://eforexcel.com/wp/wp-content/uploads/2017/07/1500000%20Sales%20Records.zip
$ unzip "1500000 Sales Records.zip"
$ mv "1500000 Sales Records.csv" part.txt
$ for i in `seq 1 10`; do cat part.txt >> test.txt ; done
$ du -sh test.txt
1.8G    test.txt

$ time wc -l test.txt
15000000 test.txt

real    0m0,350s
user    0m0,143s
sys     0m0,205s

$ time perl -lnE 'END { say $. }' test.txt
15000001

real    0m1,981s
user    0m1,719s
sys     0m0,256s

$ time raku -e 'say "test.txt".IO.open.lines.elems'
15000001

real    2m51,852s
user    0m25,129s
sys     0m6,378s

# Using swap (maximum uses 2.2G swap):
# Before `raku -e ''`

$ free -m
              total        used        free      shared  buff/cache   available
Mem:          15009        1695       12604         107         708       12917
Swap:          7583           0        7583

# After `raku -e ''`

$ free -m
              total        used        free      shared  buff/cache   available
Mem:          15009         752       13923          72         332       13899
Swap:          7583         779        6804

# Swap not used
$ time raku -ne '++$ andthen END .say' test.txt
15000001

real    1m44,906s
user    2m14,165s
sys     0m0,653s

$ raku -v
This is Rakudo version 2019.11 built on MoarVM version 2019.11
implementing Perl 6.d.

3
Чи можете ви додати інформацію про терміни та фактичний вихід wc(який повинен містити розмір файлу). Дякую.
Елізабет Маттійсен

Оновити запитання - доданий приклад для відтворення
TheAthlete

2
@TheAthlete Дякую за додану інформацію. Я думаю, що це, ймовірно, буде історично цікавим [raku] SO через імовірно, що ракудо стабільно закриває розрив у продуктивності протягом найближчих років, тому, будь ласка, подумайте про додавання ще декількох бітів інформації. По-перше, хоч і зрозуміло, що ви використовуєте недавнє ракудо (тому що ви пишете raku), все-таки було б добре мати raku -vвихід. Також, будь ласка, подумайте про те, щоб додати результат моменту моєї поточної пропозиції. Крім того, я можу розглянути можливість переходу на 'ascii'декодер пізніше цих вихідних, щоб створити кращий час.
raiph

1
Зі сторони: -lпрапор для perl значно сповільнює perl, і це не корисно в цьому випадку. На моїй машині файл із випадковою довжиною рядка та близько 200 тис. Рядків, видалення -lпризводить до покращення на 40%.
Сорін

Відповіді:


8

Один варіант, який все ще може бути досить повільним порівняно з, perlале варто порівняти:

raku -ne '++$ andthen END .say' test.txt

Параметр lкомандного рядка є зайвим.

$ є анонімним скаляром держави.

andthenтестує, що визначено його lhs, і якщо так, встановлює це значення як тему ( $_), а потім оцінює його rhs.

ENDсхожий на perl's END. Зауважте, що він повертається Nilдо, andthenале це не має значення, оскільки ми використовуємоEND оператор 'для його побічного ефекту.

На швидкість цього коду вплине кілька речей. Деякі речі, про які я можу придумати:

  • Запуск компілятора накладні. Ігноруючи будь-які використовувані модулі, rakuкомпілятор Rakudo має накладні витрати приблизно на десяту частину секунди для типового обладнання, порівняно з досить мізерним perl.

  • Поняття "лінія". У perlпонятті оброблення рядків за замовчуванням є читання рядів байтів, деякі з яких представляють кінець рядка. У rakuпонятті оброблення рядків за замовчуванням є читання рядка UTF-8, частина з якого представляє кінці рядка. Таким чином, perlвиникає лише накладне покриття декодера ASCII (або розширеного ASCII), тоді як rakuвиникає накладне покриття декодера UTF-8.

  • Оптимізації компілятора. perlяк правило, оптимізовано до макс. Мене не здивує, якщо perl -lnE 'END {say $.}' test.txtскористатися якимись розумними оптимізаціями. На відміну від цього, робота над оптимізацією Ракудо ще в перші дні її відносно.

Єдине, що я думаю, що хтось може зробити щодо першого та останнього із трьох згаданих вище пунктів - це почекати N років та / або сприяти вдосконаленню компілятора.

Буде спосіб обходити UTF-8 за замовчуванням raku. Можливо, щось на кшталт наступного вже виконується і значно швидше, ніж за замовчуванням raku, принаймні ігноруючи накладні витрати використання модуля під назвою foo:

raku -Mfoo -ne '++$ andthen END .say' test.txt

де модуль fooперемикає кодування за замовчуванням для вводу / виводу файлу на ASCII або будь-що з доступних кодувань .

Я не перевіряв, чи справді це можливо зробити в поточному ракудо, але був би здивований, якби не він.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.