Come emulare wc -l in Raku


9

In perl 5, puoi emulare wc -lusando oneliner:

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

Come implementare questa funzionalità su Raku

Se si tenta di implementare questo:

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

risulta essere lento e utilizza molta memoria

Informazioni per la riproduzione:

$ 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
Potresti aggiungere informazioni sulla tempistica e l'output effettivo di wc(che dovrebbe includere le dimensioni del file). Grazie.
Elizabeth Mattijsen,

Domanda di aggiornamento - esempio aggiunto per la riproduzione
TheAthlete

2
@TheAthlete Grazie per le informazioni aggiunte. Penso che probabilmente questo sarà un [raku] storicamente interessante a causa della presunta costante chiusura del gap prestazionale da parte di rakudo nei prossimi anni, quindi ti preghiamo di considerare di aggiungere un paio di ulteriori informazioni. Innanzitutto, anche se è chiaro che stai usando un rakudo recente (perché stai scrivendo raku), sarebbe comunque utile avere un raku -voutput. Inoltre, ti preghiamo di considerare di aggiungere l'output dei tempi del mio suggerimento attuale. Inoltre, potrei cercare di passare al 'ascii'decodificatore più tardi questo fine settimana per produrre un momento migliore.
Raiph,

1
Nota -la margine : il flag per perl rallenta significativamente il perl e non è utile in questo caso. Sulla mia macchina per un file con lunghezza della linea casuale e circa 200k linee, la rimozione -lcomporta un miglioramento del 40%.
Sorin,

Risposte:


8

Un'opzione che è ancora probabilmente piuttosto lenta rispetto a perlma vale la pena confrontare:

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

L' lopzione della riga di comando è ridondante.

$ è uno stato anonimo scalare.

andthenverifica che sia definito il suo lhs e, in tal caso, imposta quel valore come argomento ( $_) e quindi valuta il suo rhs.

ENDè simile a perl's END. Nota che ritorna Nilal andthenma non importa qui perché stiamo usando l' ENDistruzione di s per il suo effetto collaterale.

Diverse cose influiranno sulla velocità di questo codice. Alcune cose che mi vengono in mente:

  • Overhead di avvio del compilatore. Ignorando qualsiasi modulo utilizzato, il rakucompilatore Rakudo ha un sovraccarico di avvio di circa un decimo di secondo sull'hardware tipico rispetto a uno piuttosto trascurabile per perl.

  • La nozione di "linea". In perl, la nozione predefinita di elaborazione della linea è la lettura di una serie di byte, alcuni dei quali rappresentano una fine della linea. In raku, la nozione predefinita di elaborazione della linea è la lettura di una stringa UTF-8, alcune delle quali rappresentano le estremità della linea. Pertanto, perlcomporta solo l'overhead di lettura di un decoder ASCII (o Extended ASCII), mentre rakuincorre nell'overhead di lettura di un decoder UTF-8.

  • Ottimizzazioni del compilatore. perlè generalmente ottimizzato al massimo. Non mi sorprenderebbe se perl -lnE 'END {say $.}' test.txtsfrutta alcune ottimizzazioni intelligenti. Al contrario, il lavoro sull'ottimizzazione di Rakudo è ancora agli inizi relativamente parlando.

Le uniche cose che penso che chiunque possa fare riguardo al primo e all'ultimo dei tre punti che ho menzionato sopra sono aspettare N anni e / o contribuire al miglioramento del compilatore.

Ci sarà un modo per aggirare UTF-8 di raku di default. Forse qualcosa come il seguente è già fattibile e significativamente più veloce del default di raku, almeno ignorando il sovraccarico dell'uso di un modulo chiamato foo:

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

dove modulo foocambia la codifica predefinita per l'I / O dei file in ASCII o qualunque altra tra le codifiche disponibili .

Non ho verificato che ciò sia effettivamente possibile nell'attuale Rakudo, ma sarei sorpreso se non lo fosse.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.