Die Julia-Dokumentation beschreibt Speicher vorbelegen für Array
, um die Leistung zu verbessern, indem die Speicherbereinigung vermieden wird. Ist das möglich mit einem String
, das ist schließlich ein Vektor? String
Quellcode ist hier .
Mein Anwendungsfall ist, dass ich große Textdumps verarbeite, indem ich readuntil()
verwende, um einen Chunk zu erhalten, und dann regex match()
oder matchall()
oder replace()
. Ich habe es bereits in Perl programmiert, möchte aber sehen, ob Julia schneller sein kann. Ich kenne bereits die Länge der längsten Zeichenfolge, die ich verarbeiten muss.
Ich erwarte, dass Festplatten-E / A der größte Engpass sein wird, bin aber daran interessiert, alles zu erfahren, was helfen wird. Ich begrüße alle Vorschläge zu möglichen Methoden, um den Prozess zu beschleunigen.
Erstens,
"Vorzeitige Optimierung ist die Wurzel allen Übels" - Donald Knuth
Nachdem das gesagt wurde, zeigt der replace
Code in Base an, dass er den Quellstring liest und Übereinstimmungen findet, die er ersetzen soll, und er schreibt Teile des resultierenden Strings in einen IOBuffer. Nach der Verarbeitung liest es den Output String vom IOBuffer. Im Wesentlichen macht dies zwei Kopien des Quellstrings. Wenn eine maximale Länge des Input-Strings (und damit auch des Outputs) bekannt ist, kann der IOBuffer in replace
anstelle von allocated wiederverwendet werden.
Um diese Analyse in Code zu fassen, definieren Sie das folgende replace!
(basierend auf replace
):
Und jetzt,
%Vor% führt einen Austausch durch, ohne den IOBuffer zuzuweisen. Nach dem replace!
kann out
wiederverwendet werden (es ist wieder leer um takebuf_string
in replace!
. Benchmarking zeigt, dass dies die Zuteilung um 50% reduziert und auch den Prozess beschleunigt. Wenn viele replace
Statements verwendet werden, wie Sie in der Frage vorschlagen, sollte dies eine 30% oder mehr Verbesserung geben.
Wenn Sie das versuchen, wäre es schön, ein echtes Benchmark-Ergebnis zu hören. Vielleicht sollte eine Version von replace!
in Base eingefügt werden.
In Julia 0.6 ist es einfacher, eine noch optimiertere Version zu versuchen. Insbesondere können ein IOBuffer und ein String den gleichen Speicher teilen. Die Funktion replace
schreibt in einen IOBuffer und verarbeitet einen String, so dass wir replace!
ohne Zuteilungen ausführen können.
Eine Reihe von replace!
-Anweisungen kann zwischen zwei im Voraus zugewiesenen Puffern wechseln und (fast) jegliche Zuweisung vermeiden.
Konkreter:
%Vor%Und um diese Funktion zu steuern und Puffer vorzubelegen, machen wir:
%Vor% Die Funktion switcheroo!
ersetzt hello
durch whats up
und wieder zurück. Es ist einfach, den Code so zu ändern, dass er eine Reihe von replace
behandelt, wie es die Frage erfordert.
Anmerkungen:
Dies ist enger mit Julia String Interna verbunden und kann daher nicht stabil sein für zukünftige Julia Versionen (aber genauso effiziente Alternativen werden wahrscheinlich bleiben).
Es gibt immer noch zwei (lästige!) Zuordnungen pro replace!
für die zwei erstellten SubString-Werte. Diese Zuweisungen sind 64 Bytes und wachsen nicht mit der String-Größe.
Tags und Links string arrays performance memory-management julia-lang