Qu'est-ce qui est plus rapide, Clojure ou ClojureScript (et pourquoi)?
Si je devais deviner, je suis sûr que la réponse est Clojure, mais je ne sais pas pourquoi. Logiquement (pour moi) il semble que ClojureScript devrait être plus rapide:
les deux sont "dynamiques" , mais ClojureScript
- Compile en JavaScript, en cours d'exécution sur V8
- le moteur V8 est sans doute le moteur de langage dynamique le plus rapide il y a
- V8 est écrit en C
alors que Clojure:
- Est aussi dynamique
- s'Exécute dans JVM, qui n'a pas de support dynamique intégré, donc je pense que JVM doit donc faire tout ce que V8 fait aussi, pour permettre le support dynamique
- et Java est plus lent que C
alors comment Clojure pourrait-il être plus rapide que Clojrescript? Est-ce que "dynamique" signifie quelque chose de différent quand on dit que JavaScript est dynamique et Clojure est dynamique? Que suis-je pas voir?
(bien sûr, si ClojureScript en effet plus rapide, alors le raisonnement ci-dessus - il correct?)
je suppose, Qu'est-ce que Clojure compile pour....est au moins une partie de la question. Je sais que la partie JVM ne peut pas être qu'un simple interpréteur (sinon ClojureScript serait plus rapide), mais Clojure ne peut pas compiler en bytecode régulier, car il n'y a pas de "dynamique" dans la JVM. Quelle est donc la différence entre la façon dont ClojureScript est compilé/exécuté et la façon dont Clojure est compilé/excécuté et la façon dont Java est compilé/exécuté, et les différences de performance impliquées dans chacun?
3 réponses
cette question est difficile à répondre avec précision, sans référence à une tâche de benchmark spécifique (ou même à des versions spécifiques de Clojure ou de ClojureScript).
cela dit, dans la plupart des cas, je m'attendrais à ce que Clojure soit un peu plus rapide. Raisons:
- Clojure compile vers le bas statique code, donc il ne fait pas de recherche dynamique à l'exécution. Ceci est très important: le code haute performance produit souvent un bytecode C'est très similaire à Java statiquement typé. La question semble faire la fausse hypothèse qu'un langage dynamique doit faire des recherches de méthode dynamique à l'exécution: ce n'est pas toujours le cas (et n'est généralement pas dans Clojure)
- la JVM JIT est très bien conçue, et je crois qu'elle est encore un peu meilleure que les JITs JavaScript, malgré la qualité de la V8.
- si vous avez besoin de simultanéité ou besoin de profiter de plusieurs noyaux alors clairement il n'y a pas puisque JavaScript est mono-threadé.....
- le compilateur Clojure est plus mature que ClojureScript, et a eu beaucoup de travail d'ajustement de performance au cours des dernières années (y compris des choses comme le support primitif, les protocoles, etc.)
bien sûr, il est possible d'écrire rapide ou lente code dans n'importe quelle langue. Cela fera plus de différence que la différence fondamentale entre les implémentations de langue.
Et plus fondamentalement, votre le choix entre Clojure et ClojureScript ne devrait pas être une question de performance. Les deux offrent des avantages de productivité convaincants. Le principal facteur déterminant devrait être:
- si vous voulez exécuter sur le web, utilisez ClojureScript
- si vous voulez exécuter sur le serveur dans un environnement JVM, utilisez Clojure
en fait, V8 est écrit en C++. Cependant, fait essentiellement la même chose que le JVM, et JVM est écrit dans le code Javascript C. V8 JITs et exécute le code JIT'D. De même, JVM JIT compile (ou hotspot compiles) bytecode (pas Java) et exécute le code généré.
Bytecode n'est pas statique, comme Java. En fait, il peut être assez dynamique. Java, par contre, est essentiellement statique, et il n'est pas correct de confondre Java avec bytecode. Le compilateur java transforme Java le code source dans le bytecode, et le JVM exécute le bytecode. Pour plus d'informations, je vous recommande de consulter le blogue de John Rose (exemple). Il y a beaucoup de bonnes informations. Aussi, essayez de chercher des conférences par Cliff Click (comme celui-ci).
de même, le code Clojure est directement compilé en bytecode, et la JVM fait alors le même processus avec ce bytecode. Compiler Clojure se fait généralement à l'exécution, ce qui n'est pas le processus le plus rapide. De même, l' traduction de Clojurescript en Javascript n'est pas rapide non plus. La traduction de Javascript en format exécutable par V8 est évidemment très rapide. Clojure peut être en avance sur le temps compilé en bytecode cependant, et cela peut éliminer beaucoup de frais généraux de démarrage.
comme vous l'avez dit, il n'est pas non plus vraiment correct de dire que la JVM interprète bytecode. La version 1.0 n'a que plus de 17 ans!
traditionnellement, il y avait deux modes de compilation. Le premier mode est un JIT (Just in Temps) compilateur. Où bytecode est traduit directement en code machine. La compilation JIT de Java s'exécute rapidement, et ne génère pas de code hautement optimisé. Il fonctionne OK.
le second mode s'appelle le compilateur hotspot. Le compilateur hotspot est très sophistiqué. Il démarre le programme, très rapidement en mode interprété, et il les analyse comme le programme s'exécute. Comme il détecte les points chauds (points dans le code qui s'exécutent fréquemment), il compilera ceux-ci. Alors que le compilateur JIT doit être rapide parce que rien n'exécute à moins que ce ne soit JIT'EED le compilateur hotspot peut se permettre de passer du temps supplémentaire pour optimiser le snot hors du code qu'il est en train de compiler.
en Outre, il peut revenir en arrière et revoir le code plus tard et s'appliquent encore plus d'optimisations, si nécessaire et possible. C'est le point où le compilateur hotspot peut commencer à battre C/C++compilé. Parce qu'il a une connaissance de l'exécution du code, il peut se permettre d'appliquer des optimisations qu'un compilateur C/C++ statique ne peut pas faire. Par exemple, il peut fonctions virtuelles en ligne.
Hotspot a une autre caractéristique, qui à ma connaissance, aucun autre environnement n'a, il peut aussi désoptimiser le code si nécessaire. Par exemple, si le code prenait continuellement une seule branche, et que celle-ci était optimisée et que les conditions d'exécution changeaient forçant le code à descendre l'autre branche (non optimisée), la performance devient soudainement terrible. Hotspot peut désoptimiser cette fonction et commencer l'analyse à nouveau à comprendre comment le faire fonctionner mieux.
un inconvénient de hotspot est qu'il commence un peu lent. Un changement dans la JVM Java 7 a été de combiner le compilateur JIT et le compilateur hotspot. Ce mode est nouveau, cependant, et ce n'est pas par défaut, mais une fois qu'il est l'initiale de démarrage devrait être bon et alors il peut commencer à l' optimisations avancées que le JVM est si bon à.
Cheers!
ce n'est pas tant une réponse qu'un commentaire historique: tant la VM HotSpot que le moteur V8 js trouvent leur origine dans le projet Self de Sun Microsystems, dont je pense qu'ils ont prototypé une grande partie de la technologie qui leur permet de fonctionner aussi vite qu'ils le font. Quelque chose à considérer en comparant les deux. Je l'ai posté un commentaire, mais le système de réputation, m'ont empêché.