W Perlu 5 możesz emulować wc -l
za pomocą oneliner:
perl -lnE 'END {say $.}' test.txt
Jak wdrożyć tę funkcjonalność w Raku
Jeśli spróbujesz to zaimplementować:
raku -e 'say "test.txt".IO.open.lines.elems'
okazuje się powolny i zużywa dużo pamięci
Informacje do odtworzenia:
$ 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.
wc
(które powinny obejmować rozmiar pliku). Dziękuję Ci.raku
), nadal dobrze byłoby miećraku -v
wyjście. Rozważ także dodanie wyniku z mojej obecnej sugestii. Mogę też zastanowić się nad przejściem na'ascii'
dekoder później w ten weekend, aby uzyskać lepszy czas.-l
flaga dla perla znacznie spowalnia perla i w tym przypadku nie jest przydatna. Na mojej maszynie dla pliku o losowej długości linii i około 200 000 linii, usunięcie-l
skutkuje 40% poprawą.Odpowiedzi:
Jedna opcja, która prawdopodobnie będzie dość powolna w porównaniu do,
perl
ale warta porównania:Opcja
l
wiersza poleceń jest zbędna.$
jest anonimowym skalarem stanu.andthen
sprawdza, czy jego lhs jest zdefiniowane, a jeśli tak, ustawia tę wartość jako topic ($_
), a następnie ocenia jej rhs.END
jest podobny doperl
'sEND
. Zauważ, że powracaNil
do tego,andthen
ale to nie ma znaczenia, ponieważ używamyEND
instrukcji dla jej efektu ubocznego.Kilka rzeczy wpłynie na szybkość tego kodu. Niektóre rzeczy, o których mogę myśleć:
Narzut związany z uruchomieniem kompilatora. Ignorując wszystkie używane moduły,
raku
kompilator Rakudo ma narzut typowy sprzęt około około jednej dziesiątej sekundy w porównaniu do dość pomijalnegoperl
.Pojęcie „linii”. W
perl
domyślnym pojęcie przetwarzania linii czyta serię bajtów, z których część stanowią zakończenie linii. Wraku
domyślnym pojęciem przetwarzania linii jest odczytywanie łańcucha UTF-8, z których niektóre reprezentują końce linii. Zatemperl
powoduje jedynie obciążenie odczytu dekodera ASCII (lub rozszerzonego ASCII), podczas gdyraku
powoduje obciążenie odczytu dekodera UTF-8.Optymalizacje kompilatora.
perl
jest ogólnie zoptymalizowany do maksimum. Nie zaskoczyłoby mnie, gdybyperl -lnE 'END {say $.}' test.txt
skorzystał z pewnych sprytnych optymalizacji. W przeciwieństwie do tego, prace nad optymalizacją Rakudo wciąż są stosunkowo wczesne.Jedyne, co myślę, że każdy może zrobić w odniesieniu do pierwszego i ostatniego z trzech punktów, o których wspomniałem powyżej, to czekać N lat i / lub przyczyniać się do poprawy kompilatora.
Domyślnie będzie sposób obejścia UTF-8 Raku. Być może coś podobnego jest już wykonalne i znacznie szybsze niż domyślne Raku, przynajmniej ignorując narzut związany z użyciem modułu o nazwie
foo
:gdzie moduł
foo
przełącza domyślne kodowanie plików I / O na ASCII lub cokolwiek z dostępnych kodowań .Nie sprawdziłem, czy jest to wykonalne w obecnym Rakudo, ale byłbym zaskoczony, gdyby nie było.
źródło