Cómo emular wc -l en Raku

9

En perl 5, puedes emular wc -lusando oneliner:

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

Cómo implementar esta funcionalidad en Raku

Si intenta implementar esto:

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

resulta ser lento y usa mucha memoria

Información para reproducir:

$ 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.
El atleta
fuente
3
¿Podría agregar información de tiempo y la salida real de wc(que debe incluir el tamaño del archivo). Gracias.
Elizabeth Mattijsen
Pregunta de actualización - ejemplo agregado para reproducir
TheAthlete
2
@TheAthlete Gracias por la información agregada. Creo que es probable que sea un SO históricamente interesante [raku] debido al presumible cierre constante de rakudo de la brecha de rendimiento en los próximos años, así que considere agregar un par de datos adicionales. Primero, aunque está claro que está usando un rakudo reciente (porque está escribiendo raku), aún sería bueno tener raku -vsalida. Además, considere agregar el resultado de la sincronización de mi sugerencia actual. Además, puedo considerar cambiar al 'ascii'decodificador más tarde este fin de semana para producir un mejor momento.
raiph
1
En una nota al margen: la -lbandera de perl ralentiza significativamente el perl y no es útil en este caso. En mi máquina para un archivo con longitud de línea aleatoria y aproximadamente 200k líneas, la eliminación de -lresultados en una mejora del 40%.
Sorin

Respuestas:

8

Una opción que probablemente sea bastante lenta en comparación con la que perlvale la pena comparar:

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

La lopción de línea de comando es redundante.

$ Es un estado anónimo escalar.

andthenprueba que su lhs está definida, y si es así, establece ese valor como el tema ( $_) y luego evalúa sus rhs.

ENDes similar a perl's END. Tenga en cuenta que vuelve Nilal andthenpero eso no importa aquí porque estamos usando la ENDdeclaración de 's para su efecto secundario.

Varias cosas afectarán la velocidad de este código. Algunas cosas que se me ocurren:

  • Sobrecarga de arranque del compilador. Ignorando cualquier módulo que se esté utilizando, el rakucompilador Rakudo tiene una sobrecarga de inicio de aproximadamente una décima de segundo en el hardware típico en comparación con uno bastante insignificante perl.

  • La noción de una "línea". En perl, la noción predeterminada de procesamiento de línea es leer una serie de bytes, algunos de los cuales representan un final de línea. En raku, la noción predeterminada de procesamiento de línea es leer una cadena UTF-8, parte de la cual representa los extremos de la línea. Por lo tanto, perlsolo incurre en la sobrecarga de lectura de un decodificador ASCII (o ASCII extendido) mientras que rakuincurre en la sobrecarga de lectura de un decodificador UTF-8.

  • Optimizaciones del compilador. perlgeneralmente está optimizado al máximo. No me sorprendería si perl -lnE 'END {say $.}' test.txtaprovecha algunas optimizaciones inteligentes. En contraste, el trabajo en la optimización de Rakudo todavía está en sus primeros días en términos relativos.

Lo único que creo que cualquiera puede hacer sobre el primero y el último de los tres puntos que he mencionado anteriormente es esperar N años y / o contribuir a la mejora del compilador.

Habrá una forma de evitar el UTF-8-raku de forma predeterminada. Quizás algo como lo siguiente ya es factible y significativamente más rápido que el valor predeterminado de raku, al menos ignorando la sobrecarga de usar un módulo llamado foo:

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

donde el módulo foocambia la codificación predeterminada para E / S de archivo a ASCII o lo que sea de las codificaciones disponibles .

No he comprobado que esto sea factible en el Rakudo actual, pero me sorprendería si no fuera así.

raiph
fuente