Ich lerne F # und eine Sache, die mich in Bezug auf diese Sprache beschäftigt, ist Leistung. Ich habe einen kleinen Benchmark geschrieben, in dem ich idiomatische F # mit imperativem Code, der in derselben Sprache geschrieben ist, vergleiche - und zu meiner Überraschung kommt die funktionale Version wesentlich schneller heraus.
Der Benchmark besteht aus:
Hier ist der Code:
%Vor%Unabhängig von der Dateigröße ist die "F # -Stil" -Version in etwa 75% der Zeit der "C # -Stil" -Version abgeschlossen. Meine Frage ist, warum ist das? Ich sehe keine offensichtliche Ineffizienz in der imperativen Version.
Seq.map
unterscheidet sich von Array.map
. Da Sequenzen ( IEnumerable<T>
) erst beim Aufzählen ausgewertet werden, findet im F # -Stil keine Berechnung statt, bis File.WriteAllLines
durch die von Seq.map
erzeugte Sequenz (nicht Array) läuft.
Mit anderen Worten, Ihre C # -Stil-Version kehrt alle Zeichenfolgen um und speichert die umgekehrten Zeichenfolgen in einem Array und führt dann eine Schleife durch das Array durch, um in die Datei zu schreiben. Die F # -Stil-Version kehrt alle Zeichenfolgen um und schreibt sie mehr oder weniger direkt in die Datei. Das bedeutet, dass der C # -Stil dreimal die gesamte Datei durchläuft (in Array lesen, umgekehrtes Array erstellen, Array in Datei schreiben), während der Code im F # -Stil die gesamte Datei nur zweimal durchläuft (in Array lesen, schreiben umgekehrte Zeilen in Datei).
Sie würden die beste Leistung erzielen, wenn Sie File.ReadLines
anstelle von File.ReadAllLines
kombiniert mit Seq.map
verwenden - aber Ihre Ausgabedatei müsste sich von Ihrer Eingabedatei unterscheiden, wie Sie schreiben würden Ausgabe, während noch vom Eingang gelesen wird.
Das Formular Seq.map hat mehrere Vorteile gegenüber einer regulären Schleife. Es kann die Funktionsreferenz nur einmal vorberechnen; es kann die Variablenzuweisungen vermeiden; und es kann die Eingabesequenzlänge verwenden, um das Ergebnisarray zu präsize.
Tags und Links f# performance