Como emular wc -l em Raku

9

No perl 5, você pode emular wc -lusando 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.
O atleta
fonte
3
Você poderia adicionar informações de tempo e a saída real de wc(que deve incluir o tamanho do arquivo). Obrigado.
Elizabeth Mattijsen
Pergunta de atualização - exemplo adicionado para reproduzir
TheAthlete 28/02
2
@TheAthlete Obrigado pela informação adicionada. Eu acho que isso provavelmente será um SO historicamente interessante [raku] por causa do presumível fechamento constante do rakudo da lacuna de desempenho nos próximos anos, então, por favor, considere adicionar mais algumas informações. Primeiro, embora esteja claro que você está usando um rakudo recente (porque você está escrevendo raku), ainda seria bom ter raku -vsaí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.
raiph 28/02
11
Em uma nota lateral: a -lsinalizaçã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 -lresulta em uma melhoria de 40%.
Sorin

Respostas:

8

Uma opção que ainda é muito lenta em comparação, perlmas vale a pena comparar:

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

A lopção de linha de comando é redundante.

$ é um escalar de estado anônimo.

andthentesta se seu lhs está definido e, em caso afirmativo, define esse valor como topic ( $_) e avalia seu rhs.

ENDé semelhante ao perl's END. Observe que ele retorna Nilao, andthenmas isso não importa aqui, porque estamos usando a ENDinstruçã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 rakucompilador 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ível perl.

  • 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. Em raku, a noção padrão de processamento de linha é ler uma sequência UTF-8, algumas das quais representam o final da linha. Portanto, perlapenas incorre na sobrecarga de leitura de um decodificador ASCII (ou ASCII estendido), enquanto rakuincorre na sobrecarga de leitura de um decodificador UTF-8.

  • Otimizações do compilador. perlgeralmente é otimizado ao máximo. Não me surpreenderia se perl -lnE 'END {say $.}' test.txttirar 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:

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

em que o módulo fooalterna 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.

raiph
fonte