TL; DR Auf einem alten Rakudo .decode
ist etwa 100-mal so schnell.
In längerer Form passend zu Ihrem Code:
sub fileToCorrectUTF8Str ($fileName) { # binary file
slurp($fileName, :bin).decode
}
Leistungshinweise
Zuerst habe ich Folgendes zum Testen geschrieben:
# 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;
Auf dem Rakudo von 2018.12
TIO.run .decode
wiegt das oben Genannte ungefähr .05
Sekunden pro Million Byte Datei anstelle von ungefähr 5
Sekunden für Ihre Lösung.
Sie könnten / sollten natürlich auf Ihrem System testen und / oder spätere Versionen von Rakudo verwenden. Ich würde erwarten, dass der Unterschied in der gleichen Reihenfolge bleibt, aber dass sich die absoluten Zeiten im Laufe der Jahre deutlich verbessern. [1]
Warum ist es 100x so schnell?
Nun, zunächst einmal , @
auf einem Buf
/ Blob
explizit Raku Kräfte , die das ehemals sehen einzelne Element ( ein Puffer) als Plural Sache (eine Liste von Elementen aka mehrere Artikel s ). Dies bedeutet eine Iteration auf hoher Ebene, die für eine Million Elementpuffer sofort eine Million Iterationen / Operationen auf hoher Ebene statt nur einer ist Operation auf hoher Ebene ist.
Zweitens .decode
vermeidet die Verwendung nicht nur die Iteration, sondern verursacht nur einmal pro Datei einen relativ langsamen Overhead für Methodenaufrufe, während bei der Iteration möglicherweise eine Million .chr
Aufrufe pro Datei auftreten. Methodenaufrufe sind (zumindest semantisch) spät gebunden, was im Prinzip relativ kostspielig ist, beispielsweise wenn ein Sub anstelle einer Methode aufgerufen wird (Subs sind im Allgemeinen früh gebunden ).
Das alles sagte:
Denken Sie daran, dass der Vorbehalt leer ist [1] . Beispielsweise generieren die Standardklassen von rakudo Methodencaches, und es ist plausibel, dass der Compiler die Methode ohnehin nur einbindet, sodass der Aufwand für den Aspekt des Methodenaufrufs möglicherweise vernachlässigbar ist.
Siehe auch die Seite Leistung des Dokuments , insbesondere Vorhandenen Hochleistungscode verwenden .
Ist die Buf.Str
Fehlermeldung LTA ?
Update Siehe den Kommentar von Liz ++.
Wenn Sie versuchen, .Str
ein Buf
oder Blob
(oder ein gleichwertiges Element, z. B. das ~
Präfix) zu verwenden, wird eine Ausnahme angezeigt. Derzeit lautet die Nachricht:
Cannot use a Buf as a string, but you called the Str method on it
Das Dokument für .Str
ein Buf
/Blob
sagt derzeit:
Um in eine Str zu konvertieren, müssen Sie verwenden .decode
.
Es ist wohl LTA, dass die Fehlermeldung nicht dasselbe andeutet.
Dann wieder, bevor sie entscheidet , was ist, dies zu tun, wenn überhaupt, müssen wir was zu beachten ist und wie Folk könnte von etwas lernen, was schief geht, einschließlich Signale darüber, wie Fehlermeldungen, und auch , was und wie sie tun in Tatsache lernen derzeit und voreingenommen unsere Reaktionen auf den Aufbau der richtigen Kultur und Infrastruktur.
Insbesondere wenn die Leute leicht eine Verbindung zwischen einer Fehlermeldung, die sie sehen, und einer Online-Diskussion, die darauf eingeht, herstellen können, muss dies berücksichtigt und möglicherweise gefördert und / oder erleichtert werden.
Zum Beispiel gibt es jetzt diese SO, die dieses Problem mit der darin enthaltenen Fehlermeldung abdeckt, sodass Google wahrscheinlich jemanden hierher bringt. Sich darauf zu stützen, könnte ein geeigneterer Weg sein, als die Fehlermeldung zu ändern. Oder vielleicht auch nicht. Die Änderung wäre einfach ...
Bitte erwägen Sie, unten einen Kommentar abzugeben und / oder vorhandene Rakudo-Probleme zu durchsuchen, um festzustellen , ob eine Verbesserung der Buf.Str
Fehlermeldung in Betracht gezogen wird und / oder ob Sie ein Problem öffnen möchten, um eine Änderung vorzuschlagen. Jeder bewegte Stein ist zumindest eine großartige Übung und verbessert (unsere Sicht auf) den Berg , wenn unsere gemeinsamen Anstrengungen immer klüger werden .
Fußnoten
[1] Wie das bekannte lateinische Sprichwort Caveat Empty sagt , kann sowohl die absolute als auch die relative Leistung eines bestimmten Raku-Features und allgemein eines bestimmten Codes aufgrund von Faktoren wie den Fähigkeiten des eigenen Systems und seiner Auslastung während der Zeit immer variieren Ausführen des Codes und alle vom Compiler vorgenommenen Optimierungen. Wenn Ihr System beispielsweise "leer" ist, wird Ihr Code möglicherweise schneller ausgeführt. Wenn Sie ein oder drei Jahre warten, bis der Compiler schneller wird, sehen die Fortschritte bei der Leistung von Rakudo weiterhin vielversprechend aus .
slurp
istIO::Path.slurp
in diesem Fall nur ein Wrapper. Wenn Sie.IO.slurp
stattdessen anrufen, wird dies in meinen Benchmarks um etwa 2% schneller. Wenn Sie die Datei mit schlürfen:enc<latin1>
, erhalten Sie einen Zeichenpuffer wie bei der Standard-UTF-8-Codierung. Überspringen Sie jedoch die Überprüfung, ob die verschluckte Datei tatsächlich gültiges UTF-8 ist, das Sie beim Decodieren ausführen auf jeden Fall zu einem UTF-8-String, was dies ebenfalls um etwa 10% schneller macht.