Comment émuler wc -l dans Raku

9

Dans Perl 5, vous pouvez émuler en wc -lutilisant oneliner:

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

Comment implémenter cette fonctionnalité sur Raku

Si vous essayez de l'implémenter:

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

il s'avère lent et utilise beaucoup de mémoire

Informations à reproduire:

$ 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.
L'athlète
la source
3
Pourriez-vous ajouter des informations de synchronisation et la sortie réelle de wc(qui devrait inclure la taille du fichier). Je vous remercie.
Elizabeth Mattijsen
Question de mise à jour - exemple ajouté pour reproduire
TheAthlete
2
@TheAthlete Merci pour les informations ajoutées. Je pense qu'il est probable que ce sera un [raku] SO historiquement intéressant en raison de la fermeture constante présumée de rakudo de l'écart de performance au cours des prochaines années, alors pensez à ajouter quelques informations supplémentaires. Tout d'abord, bien qu'il soit clair que vous utilisez un rakudo récent (parce que vous écrivez raku), il serait toujours bon d'avoir une raku -vsortie. Veuillez également envisager d'ajouter la sortie du calendrier de ma suggestion actuelle. De plus, je pourrais envisager de passer au 'ascii'décodeur plus tard ce week-end pour produire un meilleur moment.
raiph
1
Sur une note latérale: le -ldrapeau pour perl ralentit considérablement le perl et ce n'est pas utile dans ce cas. Sur ma machine pour un fichier avec une longueur de ligne aléatoire et environ 200k lignes, la suppression -lentraîne une amélioration de 40%.
Sorin

Réponses:

8

Une option qui sera probablement assez lente par rapport à perlmais qui vaut la peine d'être comparée:

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

L' loption de ligne de commande est redondante.

$ est un scalaire d'état anonyme.

andthenteste que son lhs est défini, et si c'est le cas, définit cette valeur comme topic ( $_), puis évalue son rhs.

ENDest similaire à perl's END. Notez qu'il revient Nilà la andthenmais cela n'a pas d'importance ici car nous utilisons la ENDdéclaration de pour son effet secondaire.

Plusieurs choses auront un impact sur la vitesse de ce code. Quelques choses auxquelles je peux penser:

  • Frais généraux de démarrage du compilateur. Ignorant tous les modules utilisés, le rakucompilateur Rakudo a un surcoût de démarrage d'environ un dixième de seconde sur du matériel typique par rapport à un assez négligeable pour perl.

  • La notion de "ligne". Dans perl, la notion par défaut de traitement de ligne consiste à lire une série d'octets, dont certains représentent une fin de ligne. Dans raku, la notion par défaut de traitement de ligne consiste à lire une chaîne UTF-8, dont certaines représentent des fins de ligne. Par conséquent, cela perln'entraîne que la surcharge de lecture d'un décodeur ASCII (ou ASCII étendu) tandis que rakula surcharge de lecture d'un décodeur UTF-8.

  • Optimisations du compilateur. perlest généralement optimisé au maximum. Cela ne m'étonnerait pas de perl -lnE 'END {say $.}' test.txtprofiter de quelques optimisations intelligentes. En revanche, le travail sur l'optimisation de Rakudo est encore à ses débuts relativement parlant.

Les seules choses que je pense que n'importe qui peut faire à propos du premier et du dernier des trois points que j'ai mentionnés ci-dessus sont d'attendre N ans et / ou de contribuer à l'amélioration du compilateur.

Il y aura un moyen de contourner l'UTF-8 par défaut de raku. Peut-être que quelque chose comme ce qui suit est déjà faisable et beaucoup plus rapide que la valeur par défaut de raku, ignorant au moins la surcharge d'utilisation d'un module appelé foo:

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

où le module foobascule l'encodage par défaut des E / S de fichiers en ASCII ou autre parmi les encodages disponibles .

Je n'ai pas vérifié que c'est réellement faisable dans le Rakudo actuel, mais je serais surpris s'il ne l'était pas.

raiph
la source