Vitesse de compilation Java vs vitesse de compilation Scala

101

Je programme dans Scala depuis un moment et j'aime ça mais une chose qui me gêne est le temps qu'il faut pour compiler des programmes. Cela semble être une petite chose, mais avec Java, je pourrais apporter de petites modifications à mon programme, cliquer sur le bouton Exécuter dans netbeans, et BOOM, il est en cours d'exécution, et avec le temps, la compilation dans scala semble prendre beaucoup de temps. J'ai entendu dire qu'avec de nombreux grands projets, un langage de script devient très important en raison du temps de compilation, un besoin que je n'ai pas vu surgir lorsque j'utilisais Java.

Mais je viens de Java qui, d'après ce que je comprends, est plus rapide que tout autre langage compilé, et rapide à cause des raisons pour lesquelles je suis passé à Scala (c'est un langage très simple).

Je voulais donc demander, puis-je rendre Scala compiler plus rapidement et scalac sera-t-il toujours aussi rapide que javac?

utilisateur405163
la source
On dirait que certains utilisateurs sont d'accord avec vous;) twitter.com/etorreborre/status/21286172202
VonC
Go compile plus rapidement que Java. Beaucoup plus vite, ce qui veut dire quelque chose.
Daniel C.Sobral
Ahaha, dans mon cas, cela prend plusieurs minutes pour une compilation scalac moyenne avec quelques chiens LOC, fsc est légèrement plus rapide.
Jeriho

Réponses:

57

Le compilateur Scala est plus sophistiqué que celui de Java, fournissant une inférence de type, une conversion implicite et un système de type beaucoup plus puissant. Ces fonctionnalités ne sont pas gratuites, donc je ne m'attendrais pas à ce que scalac soit aussi rapide que javac. Cela reflète un compromis entre le programmeur effectuant le travail et le compilateur effectuant le travail.

Cela dit, les temps de compilation se sont déjà sensiblement améliorés, passant de Scala 2.7 à Scala 2.8, et je m'attends à ce que les améliorations se poursuivent maintenant que la poussière s'est installée sur 2.8. Cette page documente certains des efforts et des idées en cours pour améliorer les performances du compilateur Scala.

Martin Odersky fournit beaucoup plus de détails dans sa réponse.

Aaron Novstrup
la source
1
N'est-ce pas plus cette page ( lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded )?
VonC
Je suis passé de netbeans à ant + jedit (je sais que je sais, ant est pour les hommes des cavernes, mais j'évoluerai à mon rythme) pour pouvoir utiliser fsc. Mais je me demandais comment la vitesse de compilation de Clojure se compare-t-elle à celle de Scala? Il semble avoir de nombreuses fonctionnalités de Scala mais j'imagine que la syntaxe est beaucoup plus facile à analyser.
user405163
1
Nous sortons un peu du sujet ici, mais le compilateur de Clojure est extrêmement rapide (beaucoup plus rapide que javac sur des sources équivalentes). Vous avez raison de dire que c'est un langage très simple, et qu'il n'a pas de système de type statique, ce qui aide beaucoup.
Daniel Spiewak
458

Il y a deux aspects à la (manque de) vitesse du compilateur Scala.

  1. Frais généraux de démarrage plus importants

    • Scalac lui-même se compose de BEAUCOUP de classes qui doivent être chargées et compilées jit

    • Scalac doit rechercher dans le classpath tous les packages et fichiers racine. En fonction de la taille de votre chemin de classe, cela peut prendre une à trois secondes supplémentaires.

    Dans l'ensemble, attendez-vous à une surcharge de démarrage du scalac de 4 à 8 secondes, plus longue si vous l'exécutez la première fois afin que les caches de disque ne soient pas remplis.

    La réponse de Scala à la surcharge de démarrage est d'utiliser fsc ou de faire de la construction continue avec sbt. IntelliJ doit être configuré pour utiliser l'une ou l'autre option, sinon sa surcharge, même pour les petits fichiers, est déraisonnablement importante.

  2. Vitesse de compilation plus lente. Scalac gère environ 500 à 1000 lignes / sec. Javac gère environ 10 fois cela. Il y a plusieurs raisons à cela.

    • L'inférence de type est coûteuse, en particulier si elle implique une recherche implicite.

    • Scalac doit faire deux vérifications de type; une fois selon les règles de Scala et une seconde fois après l'effacement selon les règles de Java.

    • Outre la vérification de type, il y a environ 15 étapes de transformation pour passer de Scala à Java, qui prennent toutes du temps.

    • Scala génère généralement beaucoup plus de classes par taille de fichier donnée que Java, en particulier si les idiomes fonctionnels sont fortement utilisés. La génération de bytecode et l'écriture de classe prennent du temps.

    D'un autre côté, un programme Scala de 1000 lignes peut correspondre à un programme Java de 2-3K lignes, donc une partie de la vitesse la plus lente comptée en lignes par seconde doit être compensée par plus de fonctionnalités par ligne.

    Nous travaillons sur des améliorations de vitesse (par exemple en générant des fichiers de classe en parallèle), mais on ne peut pas s'attendre à des miracles sur ce front. Scalac ne sera jamais aussi rapide que javac. Je crois que la solution résidera dans la compilation de serveurs comme fsc en conjonction avec une bonne analyse des dépendances afin que seul l'ensemble minimal de fichiers doive être recompilé. Nous y travaillons également.

Martin Odersky
la source
1
À propos de la surcharge de démarrage due au chargement de classe: une compilation anticipée en code natif à l'aide de GCJ ou de Mono aiderait-elle?
Escargot mécanique
15
Et si Scala était réécrit en C ++? : o)
marcus
Y aurait-il un avantage à utiliser l'instruction bytecode invokedynamic?
Rob Grant
40

Vous devez savoir que la compilation Scala prend au moins un ordre de grandeur plus longue que Java à compiler. Les raisons en sont les suivantes:

  1. Conventions de dénomination (un fichier XY.scalafichier n'a pas besoin de contenir une classe appelée XYet peut contenir plusieurs classes de niveau supérieur). Le compilateur peut donc avoir à rechercher plus de fichiers source pour trouver un identifiant de classe / trait / objet donné.
  2. Implicits - l'utilisation intensive des implicits signifie que le compilateur doit rechercher toute conversion implicite dans la portée pour une méthode donnée et les classer pour trouver la "bonne". ( c'est-à-dire que le compilateur a un domaine de recherche massivement augmenté lors de la localisation d'une méthode. )
  3. Le système de type - le système de type scala est bien plus compliqué que celui de Java et prend donc plus de temps CPU.
  4. Inférence de type - l'inférence de type est coûteuse en calcul et un travail qui javacn'a pas à faire du tout
  5. scalaccomprend un simulateur 8 bits d'une station de combat entièrement armée et opérationnelle, visible à l'aide de la combinaison de touches magiques CTRL-ALT-F12 pendant la phase de compilation GenICode .
oxbow_lakes
la source
3
@obox_lakes, déteste pinailler, mais Java ne faut faire l' inférence de type pour les méthodes paramétrées int a<T>(T a) {}et puis a(pls_infer_my_type). james-iry.blogspot.com/2009/04/…
Elazar Leibovich
13
@Elazar - oui, je sais. Mais il est franchement risible, à côté de scala, d'appeler cette "inférence de type"!
oxbow_lakes
19

La meilleure façon de faire Scala est avec IDEA et SBT. Configurez un projet SBT élémentaire (ce qu'il fera pour vous, si vous le souhaitez) et exécutez-le en mode de compilation automatique (commande~compile ) et lorsque vous enregistrez votre projet, SBT le recompilera.

Vous pouvez également utiliser le plug-in SBT pour IDEA et attacher une action SBT à chacune de vos configurations d'exécution. Le plug-in SBT vous offre également une console SBT interactive dans IDEA.

Dans tous les cas (SBT s'exécutant en externe ou plug-in SBT), SBT reste en cours d'exécution et ainsi toutes les classes utilisées dans la construction de votre projet sont "réchauffées" et JIT-ed et la surcharge de démarrage est éliminée. De plus, SBT ne compile que les fichiers source qui en ont besoin. C'est de loin le moyen le plus efficace de créer des programmes Scala.

Randall Schulz
la source
9

Les dernières révisions de Scala-IDE (Eclipse) sont bien meilleures pour gérer la compilation incrémentielle.

Voir " Quel est le meilleur système de construction Scala? " Pour en savoir plus.


L'autre solution consiste à intégrer fsc - compilateur hors ligne rapide pour le langage Scala 2 - (comme illustré dans ce billet de blog ) en tant que générateur dans votre IDE.

texte alternatif

Mais pas directement dans Eclipse, comme le mentionne Daniel Spiewak dans les commentaires:

Vous ne devriez pas utiliser FSC directement dans Eclipse, ne serait-ce que parce qu'Eclipse utilise déjà FSC sous la surface.
FSC est essentiellement une couche mince au-dessus du compilateur résident qui est précisément le mécanisme utilisé par Eclipse pour compiler les projets Scala.


Enfin, comme me le rappelle Jackson Davis dans les commentaires:

sbt (Simple build Tool) inclut également une sorte de compilation "incrémentale" (par exécution déclenchée ), même si elle n'est pas parfaite , et une compilation incrémentielle améliorée est en cours pour la prochaine version 0.9 sbt.

VonC
la source
2
sbt peut également faire des compilations incrémentielles
Jackson Davis
@Jackson: exécution déclenchée, c'est vrai! Je l'ai inclus dans ma réponse.
VonC
2
Vous ne devriez pas utiliser FSC directement dans Eclipse, ne serait-ce que parce qu'Eclipse utilise déjà FSC sous la surface. FSC est essentiellement une couche mince au-dessus du compilateur résident qui est précisément le mécanisme utilisé par Eclipse pour compiler les projets Scala.
Daniel Spiewak
1
FSC signifie Fast Scala Compiler - pas Fast Java Compiler
Ben McCann
@BenMcCann: oups. Droite. J'ai fixé la réponse.
VonC
6

Utilisez fsc - c'est un compilateur scala rapide qui se trouve en tâche de fond et qui n'a pas besoin d'être chargé en permanence. Il peut réutiliser l'instance précédente du compilateur.

Je ne sais pas si le plugin Netbeans scala prend en charge fsc (la documentation le dit), mais je n'ai pas pu le faire fonctionner. Essayez les versions nocturnes du plugin.

Denis Tulskiy
la source
1
Le plugin IntelliJ IDEA Scala a également une option pour utiliser fsc
Aaron Novstrup
1
@anovstrup: oui, mais il plante parfois.
Denis Tulskiy
4

Vous pouvez utiliser le plugin JRebel qui est gratuit pour Scala. Ainsi, vous pouvez en quelque sorte "développer dans le débogueur" et JRebel rechargerait toujours la classe modifiée sur place.

J'ai lu quelque part une déclaration de Martin Odersky lui-même où il dit que les recherches d'implicits (le compilateur doit s'assurer qu'il n'y a pas plus d'un seul implicite pour la même conversion afin d'exclure les ambiguïtés) peuvent occuper le compilateur. Il peut donc être judicieux de gérer les implicits avec précaution.

S'il n'est pas nécessaire que ce soit 100% Scala, mais aussi quelque chose de similaire, vous pouvez essayer Kotlin .

- Oliver

OlliP
la source
2

Je suis sûr que ce sera voté à la baisse, mais une rotation extrêmement rapide ne favorise pas toujours la qualité ou la productivité.

Prenez le temps de réfléchir plus attentivement et d'exécuter moins de micro-cycles de développement. Un bon code Scala est plus dense et plus essentiel (c'est-à-dire exempt de détails accessoires et de complexité). Cela demande plus de réflexion et cela prend du temps (du moins au début). Vous pouvez bien progresser avec moins de cycles de code / test / débogage qui sont individuellement un peu plus longs tout en améliorant votre productivité et la qualité de votre travail.

En bref: recherchez un modèle de travail optimal mieux adapté à Scala.

Randall Schulz
la source
3
Je conviens qu'il n'est pas essentiel d'avoir un cycle de rotation rapide. Mais ça ne fait pas mal, n'est-ce pas?
Elazar Leibovich
27
Je ne vais pas voter contre, mais dire que vous devriez ajuster votre modèle de travail aux limites de votre outil (la vitesse lente du compilateur) plutôt que d'essayer d'améliorer l'outil n'est pas un bon argument. En particulier, la capacité de faire des cycles de test rapides est très précieuse (même si cela ne remplace pas le besoin de réfléchir profondément, le genre qui est probablement le mieux fait loin du clavier, cela le complète bien).
Thilo
9
Je pense que la plupart de ma productivité est en fait perdue à cause de la réflexion avant de courir. Je me retrouve souvent à regarder une équation pendant de longues périodes en essayant de repérer le piège potentiel qui m'attend, tout en pensant: "Exécutez-le!" dans le fond de ma tête. Et bien sûr, lorsque je lance le programme, j'apprends beaucoup plus que ce que j'aurais probablement avec une heure ou deux de méditation. La méditation est bonne, mais je pense que j'ai eu une utilisation très optimale de la compilation / méditation incrémentale avec java.
user405163
2
Cela revient également à suggérer que Shakespeare ne devrait pas utiliser de correcteur orthographique, mais plutôt réfléchir davantage à ce qu'il veut dire. Le correcteur orthographique automatisé aide à résoudre un ensemble de problèmes complètement différents.
Thilo