Quels changements à la JVM seraient les plus bénéfiques pour le compilateur et le runtime Scala?
Les langages dynamics bénéficieront grandement des performances de l’introduction du code d’octet InvokeDynamic
prévu pour arriver dans JVM 7 et Scala bénéficiera probablement de la récursion de la queue (on ne sait pas si elle apparaîtra dans JVM 8 ou une version ultérieure).
Quels autres changements Scala, avec ses fonctionnalités actuelles, pourrait-il apporter à la JVM? Ces changements sont-ils à l’horizon?
Plus précisément, y a-t-il des modifications apscopes à la machine virtuelle Java pour améliorer les performances avec les fermetures et les fonctions en tant qu’objects?
En gros, tout ce pour quoi John Rose fait campagne 🙂
Fixnums – Pour éliminer le coût des primitives de boxing / unboxing.
Poignées de méthode – Accélérer les fonctions d’ordre supérieur et permettre à la JVM de les optimiser plus efficacement. Les types SAM peuvent parfois nécessiter un basculement / basculement maladroit entre les sites d’appels monomorphes et mégamorphes, ce qui empêche leur insertion.
Continuations – Pour prendre en charge la conception asynchrone / concurrente, conformément à node.js
Interface Injection – Simplifie la composition de mixin et l’implémentation de rôles, et élimine le besoin de générer des classes intermédiaires et de rendre les types de structures possibles sans reflection dans de nombreux cas.
Optimisation de l’appel de queue – Devrait être une évidence 🙂
La réification est souvent citée comme quelque chose qui profiterait à l’appariement de Scala, mais cela coûterait très cher en termes d’interopérabilité, étant donné les différents schémas de variance utilisés par les deux langues. À ce stade, je pense que la réification peut en fait causer plus de tort que de bien.
Je pense également qu’il n’est pas raisonnable de s’attendre à tout ce qui pourrait compromettre la compatibilité avec Java. Ça n’arrivera pas.
Il y a quelques fonctionnalités de Scala qui seraient mieux implémentées dans la JVM, par exemple:
Génériques accessibles à l’exécution. Actuellement, le scalac enregistre les types de génériques en tant que champs cachés (si la classe en question est une classe de cas). Cela rend les génériques dans les classes de cas inutilement coûteux.
Variance du site de déclaration. Scala spécifie la variance des parameters de type sur le site de définition, alors que Java le fait sur le site d’appel. Il est très peu probable que cela soit corrigé, car cela briserait tout le code Java générique existant.
Optimisation des appels de queue. Scalac peut effectuer lui-même une optimisation des appels de queue, mais uniquement dans le cas le plus simple (auto-récursif). Tout autre appel de queue utilisera un espace de stack comme dans la JVM.
Suppression des pointeurs nuls. Scala peut déjà gérer les références NULL avec l’ option [A] , mais en raison de leur présence sur la machine virtuelle Java, la référence à l’option elle-même peut être nulle ou son paramètre peut être nul. Donc, vous n’obtenez pas de garantie de non-null-ness comme dans Haskell.
EDIT: Ajout de la variance du site de déclaration à la liste.
Les types de valeurs aideraient un peu les performances des tuples et des classes de cas. L’parsing d’échappement permet de réduire un peu les allocations de tas de tels objects, mais pour le moment, la JVM ne peut pas aligner suffisamment certains appels de méthode et ne peut donc pas éliminer les allocations de tas pour ces petits objects immuables. Cela conduit à une mise en tas et à un temps d’exécution supérieur de 3 à 4 fois.
Les types de valeur permettent également d’augmenter la localité des données et de réduire l’utilisation de la mémoire. Par exemple, dans un tableau simple [(Int, Int)], chaque entrée de tableau aura un en-tête d’un pointeur + en-tête d’object. Avec les types de valeur, cette surcharge pourrait être complètement éliminée.
Les gens se concentrent souvent sur InvokeDynamic – sans se rendre compte que le framework MethodHandles présente de nombreux autres avantages, même si les références de méthode fournies par MH ne sont jamais invoquées de manière dynamic.
MethodHandles est presque comme une forme performante de “Reflection done right”.
Tout langage qui fait un usage intensif de la reflection peut très bien tirer parti de l’utilisation de MethodHandles dans l’environnement d’exécution du langage.