Java-Kompilierungsgeschwindigkeit vs Scala-Kompilierungsgeschwindigkeit

100

Ich habe eine Weile in Scala programmiert und es gefällt mir, aber eine Sache, die mich ärgert, ist die Zeit, die zum Kompilieren von Programmen benötigt wird. Es scheint eine kleine Sache zu sein, aber mit Java könnte ich kleine Änderungen an meinem Programm vornehmen, auf die Schaltfläche "Ausführen" in Netbeans klicken und BOOM wird ausgeführt, und das Kompilieren in Scala scheint im Laufe der Zeit viel Zeit in Anspruch zu nehmen. Ich höre, dass bei vielen großen Projekten eine Skriptsprache aufgrund des Zeitaufwands beim Kompilieren sehr wichtig wird, ein Bedarf, den ich bei der Verwendung von Java nicht gesehen habe.

Aber ich komme aus Java, das meines Wissens schneller ist als jede andere kompilierte Sprache und aus den Gründen, aus denen ich zu Scala gewechselt bin (es ist eine sehr einfache Sprache), schnell ist.

Also wollte ich fragen, ob ich Scala schneller kompilieren kann und ob Scalac jemals so schnell wie Javac sein wird.

user405163
quelle
Es sieht so aus, als ob einige Benutzer Ihnen zustimmen;) twitter.com/etorreborre/status/21286172202
VonC
Go kompiliert schneller als Java. Viel schneller, was etwas sagt.
Daniel C. Sobral
Ahaha, in meinem Fall dauert es einige Minuten für eine durchschnittliche Skalac-Kompilierung mit wenigen Hundert LOC, fsc ist etwas schneller.
Jeriho

Antworten:

57

Der Scala-Compiler ist komplexer als der von Java und bietet Typinferenz, implizite Konvertierung und ein viel leistungsfähigeres Typsystem. Diese Funktionen sind nicht kostenlos, daher würde ich nicht erwarten, dass Scalac jemals so schnell wie Javac ist. Dies spiegelt einen Kompromiss zwischen dem Programmierer, der die Arbeit erledigt, und dem Compiler, der die Arbeit erledigt, wider.

Trotzdem haben sich die Kompilierungszeiten von Scala 2.7 auf Scala 2.8 bereits merklich verbessert, und ich gehe davon aus, dass sich die Verbesserungen fortsetzen werden, sobald sich der Staub auf 2.8 gelegt hat. Diese Seite dokumentiert einige der laufenden Bemühungen und Ideen zur Verbesserung der Leistung des Scala-Compilers.

Martin Odersky liefert in seiner Antwort viel mehr Details.

Aaron Novstrup
quelle
1
Ist nicht mehr diese Seite ( lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded )?
VonC
Ich habe von Netbeans zu Ant + Jedit gewechselt (ich weiß, ich weiß, Ant ist für Höhlenmenschen, aber ich werde mich in meiner eigenen Zeit weiterentwickeln), damit ich fsc verwenden kann. Aber ich habe mich gefragt, wie ist die Kompilierungsgeschwindigkeit von Clojure im Vergleich zu Scala? Es scheint viele der Funktionen in Scala zu haben, aber ich stelle mir vor, dass die Syntax viel einfacher zu analysieren ist.
user405163
1
Wir kommen hier ein bisschen vom Thema ab, aber der Compiler von Clojure ist unglaublich schnell (viel schneller als Javac bei gleichwertigen Quellen). Sie haben Recht, dass es eine wirklich einfache Sprache ist und es kein statisches Typsystem gibt, was ziemlich hilfreich ist.
Daniel Spiewak
457

Die (fehlende) Geschwindigkeit des Scala-Compilers hat zwei Aspekte.

  1. Höherer Startaufwand

    • Scalac selbst besteht aus vielen Klassen, die geladen und jit-kompiliert werden müssen

    • Scalac muss den Klassenpfad nach allen Root-Paketen und Dateien durchsuchen. Abhängig von der Größe Ihres Klassenpfads kann dies ein bis drei zusätzliche Sekunden dauern.

    Erwarten Sie insgesamt einen Startaufwand für Scalac von 4 bis 8 Sekunden, der länger ist, wenn Sie ihn zum ersten Mal ausführen, damit die Festplatten-Caches nicht gefüllt werden.

    Scalas Antwort auf den Startaufwand besteht darin, entweder fsc zu verwenden oder kontinuierlich mit sbt zu erstellen. IntelliJ muss für die Verwendung beider Optionen konfiguriert werden, da sonst der Overhead selbst für kleine Dateien unangemessen groß ist.

  2. Langsamere Kompilierungsgeschwindigkeit. Scalac verwaltet ungefähr 500 bis 1000 Linien / Sek. Javac schafft das ungefähr zehnmal. Dafür gibt es mehrere Gründe.

    • Typinferenz ist kostspielig, insbesondere wenn es sich um eine implizite Suche handelt.

    • Scalac muss die Typprüfung zweimal durchführen. einmal nach den Regeln von Scala und ein zweites Mal nach dem Löschen nach den Regeln von Java.

    • Neben der Typprüfung gibt es ungefähr 15 Transformationsschritte von Scala nach Java, die alle Zeit in Anspruch nehmen.

    • Scala generiert in der Regel viel mehr Klassen pro Dateigröße als Java, insbesondere wenn häufig funktionale Redewendungen verwendet werden. Die Bytecode-Generierung und das Schreiben von Klassen brauchen Zeit.

    Auf der anderen Seite könnte ein Scala-Programm mit 1000 Zeilen einem Java-Programm mit 2-3 KB Zeilen entsprechen, sodass ein Teil der langsameren Geschwindigkeit, wenn sie in Zeilen pro Sekunde gezählt wird, gegen mehr Funktionalität pro Zeile abgewogen werden muss.

    Wir arbeiten an Geschwindigkeitsverbesserungen (zum Beispiel durch paralleles Generieren von Klassendateien), aber an dieser Front kann man keine Wunder erwarten. Scalac wird niemals so schnell sein wie Javac. Ich glaube, die Lösung wird darin bestehen, Server wie fsc in Verbindung mit einer guten Abhängigkeitsanalyse zu kompilieren, sodass nur der minimale Satz von Dateien neu kompiliert werden muss. Daran arbeiten wir auch.

Martin Odersky
quelle
1
Informationen zum Startaufwand aufgrund des Ladens von Klassen: Würde eine frühzeitige Kompilierung in nativen Code mit GCJ oder Mono helfen?
Mechanische Schnecke
14
Was wäre, wenn Scala in C ++ neu geschrieben würde? : o)
Marcus
Wäre die Verwendung des Befehls invokedynamic bytecode von Vorteil?
Rob Grant
40

Sie sollten sich bewusst sein, dass die Kompilierung von Scala mindestens eine Größenordnung länger dauert als die von Java. Die Gründe dafür sind folgende:

  1. Namenskonventionen (eine Dateidatei XY.scalamuss keine aufgerufene Klasse XYenthalten und kann mehrere Klassen der obersten Ebene enthalten). Der Compiler muss daher möglicherweise mehr Quelldateien durchsuchen, um eine bestimmte Klassen- / Merkmals- / Objektkennung zu finden.
  2. Implicits - Die häufige Verwendung von Implicits bedeutet, dass der Compiler jede implizite Konvertierung im Gültigkeitsbereich nach einer bestimmten Methode durchsuchen und sie bewerten muss, um die "richtige" zu finden. ( dh der Compiler hat beim Auffinden einer Methode eine massiv vergrößerte Suchdomäne. )
  3. Das Typsystem - das Scala-Typsystem ist viel komplizierter als das von Java und benötigt daher mehr CPU-Zeit.
  4. Typinferenz - Typinferenz ist rechenintensiv und ein Job, der javacüberhaupt nicht erledigt werden muss
  5. scalacEnthält einen 8-Bit-Simulator einer voll bewaffneten und einsatzbereiten Kampfstation, der während der GenICode- Kompilierungsphase mit der magischen Tastenkombination STRG-ALT-F12 angezeigt werden kann.
oxbow_lakes
quelle
3
@obox_lakes, hasse es zu nitpicken, aber Java muss Typinferenz für parametrisierte Methoden machen int a<T>(T a) {}und dann a(pls_infer_my_type). james-iry.blogspot.com/2009/04/…
Elazar Leibovich
13
@ Elzar - ja, ich weiß. Aber es ist ehrlich gesagt lächerlich, neben Scala diese "Typinferenz" zu nennen!
oxbow_lakes
19

Der beste Weg, um Scala zu machen, ist mit IDEA und SBT. Richten Sie ein elementares SBT-Projekt ein (was es für Sie erledigt, wenn Sie möchten) und führen Sie es im automatischen Kompilierungsmodus (Befehl ~compile) aus. Wenn Sie Ihr Projekt speichern, kompiliert SBT es erneut.

Sie können auch das SBT-Plug-In für IDEA verwenden und jeder Ihrer Ausführungskonfigurationen eine SBT-Aktion hinzufügen. Das SBT-Plug-In bietet Ihnen auch eine interaktive SBT-Konsole innerhalb von IDEA.

In beiden Fällen (SBT wird extern ausgeführt oder SBT-Plug-In) wird SBT weiterhin ausgeführt, sodass alle beim Erstellen Ihres Projekts verwendeten Klassen "aufgewärmt" und JIT-ed werden und der Startaufwand entfällt. Darüber hinaus kompiliert SBT nur Quelldateien, die es benötigen. Dies ist bei weitem der effizienteste Weg, um Scala-Programme zu erstellen.

Randall Schulz
quelle
9

Die neuesten Versionen von Scala-IDE (Eclipse) verwalten die inkrementelle Kompilierung viel besser.

Weitere Informationen finden Sie unter " Was ist das beste Scala-Build-System? ".


Die andere Lösung besteht darin, fsc - Fast Offline Compiler für die Scala 2-Sprache - (wie in diesem Blog-Beitrag dargestellt ) als Builder in Ihre IDE zu integrieren.

Alt-Text

Aber nicht direkt in Eclipse, wie Daniel Spiewak in den Kommentaren erwähnt:

Sie sollten FSC nicht direkt in Eclipse verwenden, schon allein deshalb, weil Eclipse FSC bereits unter der Oberfläche verwendet.
FSC ist im Grunde eine dünne Schicht über dem residenten Compiler. Dies ist genau der Mechanismus, den Eclipse zum Kompilieren von Scala-Projekten verwendet.


Zum Schluss, wie Jackson Davis mich in den Kommentaren erinnert:

sbt (Simple Build Tool) enthält auch eine Art "inkrementelle" Kompilierung (durch ausgelöste Ausführung ), obwohl diese nicht perfekt ist. Für die kommende Version 0.9 sbt ist eine erweiterte inkrementelle Kompilierung in Arbeit.

VonC
quelle
2
sbt kann auch inkrementelle Kompilierungen durchführen
Jackson Davis
@Jackson: ausgelöste Ausführung, richtig! Ich habe es in meine Antwort aufgenommen.
VonC
2
Sie sollten nicht direkt mit FSC innerhalb von Eclipse sein, wenn auch nur , weil Eclipse bereits FSC unter der Oberfläche verwendet wird . FSC ist im Grunde eine dünne Schicht über dem residenten Compiler. Dies ist genau der Mechanismus, den Eclipse zum Kompilieren von Scala-Projekten verwendet.
Daniel Spiewak
1
FSC steht für Fast Scala Compiler - nicht Fast Java Compiler
Ben McCann
@ BenMcCann: Ups. Richtig. Ich habe die Antwort korrigiert.
VonC
6

Verwenden Sie fsc - es ist ein schneller Scala-Compiler, der als Hintergrundaufgabe fungiert und nicht ständig geladen werden muss. Es kann die vorherige Compilerinstanz wiederverwenden.

Ich bin nicht sicher, ob das Netbeans-Scala-Plugin fsc unterstützt (Dokumentation sagt es), aber ich konnte es nicht zum Laufen bringen. Versuchen Sie es mit nächtlichen Builds des Plugins.

Denis Tulskiy
quelle
1
Das IntelliJ IDEA Scala Plugin bietet auch die Option, fsc
Aaron Novstrup
1
@anovstrup: Ja, aber es stürzt manchmal ab.
Denis Tulskiy
4

Sie können das JRebel-Plugin verwenden, das für Scala kostenlos ist. Sie können sich also sozusagen im Debugger entwickeln, und JRebel lädt die geänderte Klasse immer sofort neu.

Ich habe irgendwo eine Aussage von Martin Odersky selbst gelesen, in der er sagt, dass die Suche nach Impliziten (der Compiler muss sicherstellen, dass es nicht mehr als ein einziges Implizit für dieselbe Konvertierung gibt, um Mehrdeutigkeiten auszuschließen) den Compiler beschäftigen kann. Daher ist es möglicherweise eine gute Idee, mit Implikationen vorsichtig umzugehen.

Wenn es nicht 100% Scala sein muss, sondern auch etwas Ähnliches, können Sie Kotlin ausprobieren.

- Oliver

OlliP
quelle
2

Ich bin sicher, dass dies abgelehnt wird, aber eine extrem schnelle Abwicklung ist nicht immer förderlich für Qualität oder Produktivität.

Nehmen Sie sich Zeit zum Nachdenken und führen Sie weniger Entwicklungsmikrozyklen aus. Guter Scala-Code ist dichter und wichtiger (dh frei von zufälligen Details und Komplexität). Es erfordert mehr Gedanken und das braucht Zeit (zumindest zuerst). Sie können mit weniger Code- / Test- / Debug-Zyklen, die individuell etwas länger sind, gute Fortschritte erzielen und dennoch Ihre Produktivität und die Qualität Ihrer Arbeit verbessern.

Kurzum: Suchen Sie ein optimales Arbeitsmuster, das besser zu Scala passt.

Randall Schulz
quelle
3
Ich stimme zu, dass ein schneller Durchlaufzyklus nicht unbedingt erforderlich ist. Aber es tut nicht weh, oder?
Elazar Leibovich
27
Ich werde nicht abstimmen, aber zu sagen, dass Sie Ihr Arbeitsmuster an die Einschränkungen Ihres Tools (die langsame Geschwindigkeit des Compilers) anpassen sollten, anstatt zu versuchen, das Tool zu verbessern, ist kein gutes Argument. Insbesondere die Fähigkeit, schnelle Testzyklen durchzuführen, ist sehr wertvoll (auch wenn sie nicht die Notwendigkeit eines gründlichen Denkens ersetzt, die wahrscheinlich am besten außerhalb der Tastatur durchgeführt wird, ergänzt sie sie gut).
Thilo
9
Ich denke, der größte Teil meiner Produktivität geht durch Überdenken vor dem Laufen verloren. Ich sehe mich oft über lange Zeiträume hinweg mit einer Gleichung beschäftigt, um herauszufinden, welche potenzielle Gefahr auf mich wartet, während ich denke: "Lass es einfach laufen!" in meinem Hinterkopf. Und natürlich lerne ich beim Ausführen des Programms viel mehr, als ich wahrscheinlich mit ein oder zwei weiteren Stunden Meditation hätte. Meditation ist gut, aber ich habe das Gefühl, dass ich das inkrementelle Kompilieren / Meditieren mit Java optimal nutzen konnte.
user405163
2
Dies ähnelt auch dem Vorschlag, dass Shakespeare keine Rechtschreibprüfung verwenden und stattdessen genauer überlegen sollte, was er sagen möchte. Die automatische Rechtschreibprüfung hilft bei völlig anderen Problemen.
Thilo