No perl 5, você pode emular wc -l
usando o oneliner:
perl -lnE 'END {say $.}' test.txt
Como implementar esta funcionalidade no Raku
Se você tentar implementar isso:
raku -e 'say "test.txt".IO.open.lines.elems'
acaba por ser lento e usa muita memória
Informações para reproduzir:
$ 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
(que deve incluir o tamanho do arquivo). Obrigado.raku
), ainda seria bom terraku -v
saída. Além disso, considere adicionar a saída do tempo da minha sugestão atual. Além disso, posso pensar em mudar para o'ascii'
decodificador ainda este fim de semana para produzir um tempo melhor.-l
sinalização para perl diminui significativamente o perl e não é útil neste caso. Na minha máquina, para um arquivo com comprimento de linha aleatório e cerca de 200k linhas, a remoção-l
resulta em uma melhoria de 40%.Respostas:
Uma opção que ainda é muito lenta em comparação,
perl
mas vale a pena comparar:A
l
opção de linha de comando é redundante.$
é um escalar de estado anônimo.andthen
testa se seu lhs está definido e, em caso afirmativo, define esse valor como topic ($_
) e avalia seu rhs.END
é semelhante aoperl
'sEND
. Observe que ele retornaNil
ao,andthen
mas isso não importa aqui, porque estamos usando aEND
instrução 's para seu efeito colateral.Várias coisas afetarão a velocidade desse código. Algumas coisas em que posso pensar:
Sobrecarga de inicialização do compilador. Ignorando todos os módulos que estão sendo usados, o
raku
compilador Rakudo tem uma sobrecarga de inicialização de cerca de um décimo de segundo no hardware típico, em comparação com o bastante desprezívelperl
.A noção de uma "linha". Em
perl
, a noção padrão de processamento de linha é ler uma série de bytes, alguns dos quais representam um final de linha. Emraku
, a noção padrão de processamento de linha é ler uma sequência UTF-8, algumas das quais representam o final da linha. Portanto,perl
apenas incorre na sobrecarga de leitura de um decodificador ASCII (ou ASCII estendido), enquantoraku
incorre na sobrecarga de leitura de um decodificador UTF-8.Otimizações do compilador.
perl
geralmente é otimizado ao máximo. Não me surpreenderia seperl -lnE 'END {say $.}' test.txt
tirar proveito de algumas otimizações inteligentes. Por outro lado, o trabalho de otimização de Rakudo ainda é relativamente precoce.As únicas coisas que acho que alguém pode fazer sobre o primeiro e o último dos três pontos mencionados acima são esperar N anos e / ou contribuir para a melhoria do compilador.
Haverá uma maneira de contornar o UTF-8 do raku por padrão. Talvez algo como o seguinte já seja factível e significativamente mais rápido que o padrão de raku, pelo menos ignorando a sobrecarga de usar um módulo chamado
foo
:em que o módulo
foo
alterna a codificação padrão para E / S de arquivo para ASCII ou qualquer outra das codificações disponíveis .Eu não verifiquei se isso é realmente possível no Rakudo atual, mas ficaria surpreso se não fosse.
fonte