TL; DR Em um rakudo antigo, .decode
é cerca de 100 vezes mais rápido.
No formato mais longo para corresponder ao seu código:
sub fileToCorrectUTF8Str ($fileName) { # binary file
slurp($fileName, :bin).decode
}
Notas de desempenho
Primeiro, aqui está o que escrevi para o teste:
# Create million and 1 bytes long file:
spurt 'foo', "1234\n6789\n" x 1e5 ~ 'Z', :bin;
# (`say` the last character to check work is done)
say .decode.substr(1e6) with slurp 'foo', :bin;
# fileToCorrectUTF8Str 'foo' );
say now - INIT now;
No rakudo do 2018.12
TIO.run, o .decode
peso acima é de cerca de .05
segundos por milhão de bytes, em vez de 5
segundos para a sua solução.
É claro que você pode / deve testar em seu sistema e / ou usar versões posteriores do rakudo. Eu esperaria que a diferença permanecesse na mesma ordem, mas que os tempos absolutos melhorem acentuadamente à medida que os anos passam. [1]
Por que é 100X mais rápido?
Bem, em primeiro lugar, @
em um Buf
/ Blob
explicitamente forças Raku para ver o antigo item único ( um buffer) como um plural coisa (a lista de elementos aka múltipla artigo s ). Isso significa iteração de alto nível que, para um milhão de buffer de elemento, é imediatamente um milhão de iterações / operações de alto nível, em vez de apenas uma operação de alto nível.
Segundo, o uso .decode
não apenas evita a iteração, mas gera uma sobrecarga de chamada de método relativamente lenta uma vez por arquivo, enquanto na iteração há potencialmente um milhão de .chr
chamadas por arquivo. As chamadas de método são (pelo menos semanticamente) com ligação tardia, o que é, em princípio, relativamente caro comparado a, por exemplo, chamar um sub em vez de um método (os subs são geralmente vinculados antecipadamente ).
Tudo isso disse:
Lembre-se de Advertência Vazia [1] . Por exemplo, as classes padrão do rakudo geram caches de método, e é plausível que o compilador apenas alinha o método de qualquer maneira, portanto é possível que haja uma sobrecarga insignificante para o aspecto de chamada de método.
Consulte também a página Desempenho do documento , especialmente Usar código de alto desempenho existente .
A Buf.Str
mensagem de erro é LTA ?
Atualização Veja o comentário de Liz ++.
Se você tentar usar .Str
um Buf
ou Blob
(ou equivalente, como usar o ~
prefixo nele), receberá uma exceção. Atualmente a mensagem é:
Cannot use a Buf as a string, but you called the Str method on it
O documento para .Str
em Buf
/Blob
atualmente diz:
Para converter para um Str, você precisa usar .decode
.
É indiscutivelmente LTA que a mensagem de erro não sugere a mesma coisa.
Então, novamente, antes de decidir o que fazer sobre isso, se alguma coisa, é preciso considerar o que, e como, popular poderia aprender com qualquer coisa que der errado, incluindo sinais sobre o assunto, tais como mensagens de erro, e também o que e como eles fazem em atualmente, aprendemos e influenciamos nossas reações em direção à construção da cultura e infraestrutura certas .
Em particular, se as pessoas puderem se conectar facilmente entre uma mensagem de erro que vêem e a discussão on-line que a elabora, isso precisa ser levado em consideração e talvez incentivado e / ou facilitado.
Por exemplo, agora existe um SO que cobre esse problema com a mensagem de erro; portanto, é provável que o Google encontre alguém aqui. Se você se apoiar nesse caminho, pode ser um caminho mais apropriado do que alterar a mensagem de erro. Ou talvez não. A mudança seria fácil ...
Por favor, considere comentar abaixo e / ou pesquisar problemas de rakudo existentes para ver se a melhoria da Buf.Str
mensagem de erro está sendo considerada e / ou se você deseja abrir uma questão para propor que ela seja alterada. Cada rocha movida é pelo menos um ótimo exercício e, à medida que nosso esforço coletivo se torna cada vez mais sábio, melhora (nossa visão) da montanha .
Notas de rodapé
[1] Como diz o famoso latim Caveat Empty , o desempenho absoluto e relativo de qualquer recurso raku específico e, geralmente, de qualquer código específico, está sempre sujeito a variações devido a fatores que incluem as capacidades do sistema, sua carga durante o tempo em que é executando o código e qualquer otimização feita pelo compilador. Assim, por exemplo, se seu sistema estiver "vazio", seu código poderá ser executado mais rapidamente. Ou, como outro exemplo, se você esperar um ano ou três para o compilador ficar mais rápido, os avanços no desempenho do rakudo continuam promissores .