Wie man wc -l in Raku emuliert

9

In Perl 5 können Sie wc -lmit Oneliner emulieren :

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

So implementieren Sie diese Funktionalität auf Raku

Wenn Sie versuchen, dies zu implementieren:

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

es stellt sich als langsam heraus und verbraucht viel Speicher

Informationen zur Reproduktion:

$ 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.
Der Athlet
quelle
3
Könnten Sie Timing-Informationen und die tatsächliche Ausgabe von wc(die Dateigröße enthalten sollte) hinzufügen . Vielen Dank.
Elizabeth Mattijsen
Frage
aktualisieren
2
@ TheAthlete Danke für die zusätzlichen Informationen. Ich denke, es ist wahrscheinlich, dass dies ein historisch interessantes [raku] SO sein wird, da Rakudo die Leistungslücke in den kommenden Jahren vermutlich stetig schließt. Bitte erwägen Sie, ein paar weitere Informationen hinzuzufügen. Erstens, obwohl klar ist, dass Sie ein aktuelles Rakudo verwenden (weil Sie schreiben raku), wäre es immer noch gut, eine raku -vAusgabe zu haben . Bitte denken Sie auch daran, die Ausgabe des Timings meines aktuellen Vorschlags hinzuzufügen. Vielleicht werde ich 'ascii'später am Wochenende auf den Decoder umsteigen, um eine bessere Zeit zu erzielen.
Raiph
1
-lNebenbei bemerkt: Das Flag für Perl verlangsamt das Perl erheblich und ist in diesem Fall nicht nützlich. Auf meinem Computer für eine Datei mit zufälliger Zeilenlänge und etwa 200.000 Zeilen führt das Entfernen -lzu einer 40% igen Verbesserung.
Sorin

Antworten:

8

Eine Option, die perlim Vergleich zu wahrscheinlich immer noch ziemlich langsam ist, aber einen Vergleich wert:

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

Die lBefehlszeilenoption ist redundant.

$ ist ein anonymer Staatsskalar.

andthentestet, ob sein lhs definiert ist, und setzt in diesem Fall diesen Wert als topic ( $_) und wertet dann sein rhs aus.

ENDist ähnlich wie perl's END. Beachten Sie, dass es zum zurückkehrt Nil, andthenaber das spielt hier keine Rolle, da wir die ENDAnweisung von 'als Nebenwirkung verwenden.

Verschiedene Dinge wirken sich auf die Geschwindigkeit dieses Codes aus. Einige Dinge, an die ich denken kann:

  • Compiler-Startaufwand. Ohne Berücksichtigung der verwendeten Module hat der rakuCompiler Rakudo einen Startaufwand von etwa einer Zehntelsekunde auf typischer Hardware im Vergleich zu einem ziemlich vernachlässigbaren perl.

  • Der Begriff einer "Linie". In perlwird standardmäßig eine Reihe von Bytes gelesen, von denen einige ein Zeilenende darstellen. In rakuwird standardmäßig eine UTF-8-Zeichenfolge gelesen, von der einige Zeilenenden darstellen. Somit entsteht perlnur der Lese-Overhead eines ASCII- (oder Extended ASCII-) Decoders, während rakuder Lese-Overhead eines UTF-8-Decoders anfällt.

  • Compiler-Optimierungen. perlist in der Regel auf die max optimiert. Es würde mich nicht überraschen, wenn ich perl -lnE 'END {say $.}' test.txteinige clevere Optimierungen nutzen würde. Im Gegensatz dazu befindet sich die Arbeit an der Rakudo-Optimierung relativ gesehen noch in den Anfängen.

Das einzige, was meiner Meinung nach jeder gegen den ersten und letzten der drei oben genannten Punkte tun kann, ist, N Jahre zu warten und / oder zur Verbesserung des Compilers beizutragen.

Es wird eine Möglichkeit geben, Rakus UTF-8 standardmäßig zu umgehen. Vielleicht ist so etwas wie das Folgende bereits machbar und deutlich schneller als Rakus Standard, wobei zumindest der Aufwand für die Verwendung eines Moduls namens foo:

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

Dabei fooschaltet das Modul die Standardcodierung für Datei-E / A auf ASCII oder was auch immer aus den verfügbaren Codierungen um .

Ich habe nicht überprüft, ob dies im aktuellen Rakudo tatsächlich machbar ist, wäre aber überrascht, wenn dies nicht der Fall wäre.

Raiph
quelle