Serveur minecraft

Comment utiliser le nouveau compilateur JVM JIT dans la vraie vie – Monter un serveur MineCraft

Par Titanfall , le 27 octobre 2019 - 36 minutes de lecture

[Note: please be advised that this transcript contains strong language]

Transcription

Thalinger: Je travaille pour cette petite entreprise que vous connaissez peut-être. Cette discussion ne concerne pas vraiment Twitter, mais plutôt Graal, le compilateur. La question la plus importante de toute la conférence est la suivante: "Qui a un compte Twitter?" C'est très bien, c'est presque tout le monde. Si vous n'avez pas encore de compte, créez-en un maintenant, car je veux que vous tweetiez sur mon discours et sur tous les autres que vous trouvez intéressants.

Si vous comptez parler de mon discours sur Twitter, veuillez utiliser le hashtag "twittervmteam", car vous ne le croirez peut-être pas, mais Twitter a en fait une équipe de VM et je suis dans l'équipe de VM. Deux de mes collègues s'expriment également à QCon Sao Paulo mercredi, je pense, vous pouvez en entendre parler un peu sur l'apprentissage automatique. Nous faisons un apprentissage automatique et ensuite Flavio parle de toutes les optimisations Scala que nous réalisons dans Graal.

Qu'est-ce que le graal?

Cette discussion ne concerne pas GraalVM. GraalVM est un terme marketing très malheureux, à mon avis, et je m'en fous un peu sur Twitter parce que c'est très déroutant. GraalVM est un terme générique qui consiste essentiellement en trois technologies différentes. L’un s’appelle Graal, le compilateur JIT, l’autre s’appelle Truffle, c’est un framework dans lequel vous rivalisez avec les runtimes de la langue. Ensuite, il y a quelque chose appelé Substrat VM, que vous connaissez peut-être sous le nom d'Image native. C'est là que tout le monde est super excité pour le moment et paniqué. Je parle seulement de Graal, le compilateur d'aujourd'hui.

Lorsque vous compilez un compilateur JIT, disons Java Scala ou Kotlin en bytecode Java en fichiers de classe. La machine virtuelle Java la prend, puis l’interprète, ce qui est assez lent. Ensuite, il existe un compilateur appelé juste à temps qui compile le bytecode Java en code natif pendant l'exécution de votre application. C'est pourquoi Java est aussi rapide que cela, à cause de cela. Compilateur juste à temps, c'est ce sur quoi je travaille depuis quelques années maintenant. Je vais en parler un peu plus tard.

Graal est un compilateur juste à temps pour HotSpot. Il est activement développé par Oracle Labs. Il y a un projet OpenJDK appelé Graal. La plupart du travail est en fait fait sur GitHub, si cela vous intéresse, je vais vous montrer comment construire Graal à partir de GitHub et l'utiliser avec le dernier JDK11. Graal utilise quelque chose appelé JVMCI. C'est une interface de compilateur que nous avons introduite avec JEP 243 et JDK 9 pour vous permettre de brancher un compilateur externe. Vous le verrez aussi plus tard. Graal est écrit en Java. S'il y a une chose que vous devriez retenir de cet exposé, c'est que c'est écrit en Java et que c'est très important au moins aujourd'hui. À l'avenir, cela va changer.

HotSpot a deux compilateurs JIT, l'un s'appelle C1 ou compilateur client, l'autre s'appelle C2 ou compilateur serveur. C1 est un compilateur à haut débit. Il ne fait pas autant d'optimisations que, disons, C2 et Graal. Le but de C1 est de produire rapidement du code natif afin d'éviter d'interpréter le code pour qu'il fonctionne sur du code natif. C2 est un compilateur hautement optimisateur, il prend des informations de profilage et effectue toutes les optimisations fantaisistes imaginables, un tas d’inscriptions en ligne, une analyse d’échappement, des optimisations de boucle, etc. Graal est supposé remplacer un C2. C'est un compilateur hautement optimisateur écrit en Java.

C1 et C2 sont écrits en C ++ tandis que Graal est écrit en Java. Il existe deux différences majeures entre un élément écrit en C ++ et un élément écrit en Java. C'est comment l'allocation de mémoire fonctionne, c'est la mémoire de malloc par rapport à l'allocation de quelque chose sur un tas Java. Ensuite, du moins aujourd’hui, nous devons effectuer un processus appelé amorce, car notre compilateur faisant partie de la machine virtuelle Java est écrit dans un langage que celle-ci exécute afin qu’elle se compile elle-même au démarrage. Vous le verrez aussi plus tard.

Où puis-je l'obtenir

Où l'obtiens-tu? Où trouvez-vous Graal? En fait, nous avons utilisé Graal dans le JEP 295 pour une compilation appelée "anticipation". Ce n'est pas une image native, c'est autre chose. C’est ce que nous avons fait dans 9 et c’est essentiellement un petit utilitaire de ligne de commande qui prend des fichiers de classe Java ou JAR, envoie toutes les méthodes à Graal pour le compiler et crée une bibliothèque partagée à l’autre extrémité. HotSpot peut alors récupérer cette bibliothèque partagée afin que vous puissiez ignorer l'interprétation du bytecode. Si vous avez une très grosse application, cela pourrait aider à démarrer. Je dis pourrait parce qu'il est très difficile de bien faire les choses. La différence entre celle-ci et Native Image est que celle-ci est en réalité Java alors que Native Image est un sous-ensemble de Java, ce n'est pas vraiment Java. Je n'y vais pas parce que cela prendrait trop de temps.

Ensuite, Oracle sur le JEP 317 l'a ajouté en tant que compositeur expérimental JIT. Graal y figurait déjà, mais il disait: "Maintenant, nous l'annonçons et disons, c'est un compilateur JIT externe, vous pouvez l'utiliser." Cela est arrivé à 10. Si vous utilisez un JDK 10 ou supérieur, le 9 fonctionne également parce que, lorsque nous avons introduit la fonctionnalité hors du temps, je l'ai fait pour que cela fonctionne, personne ne le savait, mais moi aussi.

Get It Demo

J'avais l'habitude de faire cette démo différemment. J'avais l'habitude de faire cette conversation dans un conteneur cloud, où j'avais créé un conteneur cloud vide afin de vous montrer que je ne trichais pas. Tout ce que je fais aujourd'hui, il vous suffit de faire ce que je fais, je n'ai rien préparé, ce qui signifie également que beaucoup de problèmes peuvent se produire, ce qui est parfois le cas. Nous verrons comment cela se passe aujourd'hui. De nos jours, il y a beaucoup de dactylographie, je ne sais pas si vous avez déjà tapé devant tant de gens, donc des fautes de frappe – certainement possibles.

J'utilise les repères DaCapo pour vous montrer quelques chiffres et ensuite d'autres choses dont j'ai besoin d'un peu plus pour exécuter le code. Ai-je besoin d'autre chose? Non je ne pense pas. JDK 11 – J'utilise 11 parce que c'est LTS. Je pourrais aussi utiliser 12, mais chacun d’entre vous utilise probablement JDK 11 en production actuellement, c’est pourquoi je l’utilise.

Nous avons mis ce type et alors cela devrait être suffisant pour cette configuration. Il s’agit de la version 11.0.2, celle que nous venons d’extraire, nous faisons la même chose ici car nous allons comparer C2 et Graal plus tard dans les points de repère. C'est pour ça que je fais ça.

Ensuite, je vais définir une variable d'environnement appelée "Options de l'outil Java" et pour tous les lancements proposés par le JDK, nous allons sélectionner automatiquement une variable d'environnement. Je vais définir un tas de choses, donc je n'ai pas à le régler tout le temps. Tout d’abord, comme vous le savez peut-être, depuis JDK 9, le GC par défaut est G1. L'enregistrement de la sortie de G1 est un peu difficile à lire. Maintenant, nous allons regarder GC, je mettrai un peu plus tard. Parallel GC est tellement plus facile à lire, nous l’utilisons. Nous avons défini une taille de tas maximale, assez petite, seulement 512 Mo. Je le fais parce que je veux que vous voyiez quand les GC se déroulent. Si la taille du segment de mémoire est trop grande, nous ne voyons pas de GC. Je ne peux donc pas vous montrer ce que je veux que vous montriez.

Nous avons également défini la taille de début du tas à 512 Mo. La raison pour laquelle je le fais est que si nous utilisons quelque chose avec C2 et Graal, parce que Graal utilise la mémoire de tas Java pour faire des compilations, l’agrandissement de tas serait différent et nous ne comparerions pas vraiment les pommes aux pommes. J'essaye de faire des pommes en pommes aussi bien que possible.

Vous savez également que depuis le JDK 9, nous avons maintenant des modules. Comme vous pouvez le constater, cette variable d’environnement a été collectée et utilisée. Je pense que le JDK contient 75 modules ish et nous recherchons des modules appelés jdk.internal.vm. Comme vous pouvez le voir, il y en a trois, l'un s'appelle jdk.internal.vm.ci, c'est JVMCI. C'est l'interface du compilateur que nous avons introduite dans neuf, il s'agit essentiellement d'une API et d'un module. Il y a évidemment une partie du code natif également parce que nous devons parler à la machine virtuelle. C'est l'interface Java. Ensuite, il y en a un autre appelé jdk.internal.vm.compiler. C'est juste un code source Graal de GitHub dans le module Java, c'est tout ce que c'est. Ensuite, il y a un peu de gestion ici, ignorez cela pour l'instant.

Comme je l'ai dit, je discutais avec un conteneur cloud et il fallait toujours un certain temps pour que le conteneur cloud apparaisse. En attendant, je parlais de moi. Nous parcourons cela rapidement, je travaille sur les machines virtuelles depuis très longtemps, pendant toutes ces 14 années, essentiellement sur les compilateurs JIT. C'est tout ce que je fais. Auparavant, je travaillais chez Sun Microsystems et Oracle dans l'équipe du compilateur HotSpot, principalement avec C2. C'est une douleur majeure dans le cul, ne le fais pas, utilise Graal. Ce sont les trois plus gros projets que j'ai réalisés chez Sun et Oracle. J'ai travaillé sur JSR 92, que vous connaissez peut-être sous le nom de descripteurs de méthode invokedynamic. Si vous utilisez Java 8 lambdas, vous utilisez invokedynamic sous le capot sans que vous le sachiez. J'ai écrit beaucoup de ce code. Il y a un paquet appelé java.lang.invoke, j'ai écrit beaucoup de ce code Java. Si cela ne fonctionne pas, vous pouvez techniquement me blâmer, mais d'autres personnes ont appliqué le code après moi. Le code que j'ai écrit était donc parfaitement correct et ils l'ont violé.

JEP 243 est l'interface dont nous avons déjà parlé. C'est essentiellement l'interface que Graal utilisait. Nous venons de l'extraire et d'en faire une API quelque peu stable. Ce n'est pas une API officielle parce que ce n'est pas un espace de noms de soutien officiel, mais stable. JEP 295, nous en avons déjà parlé, ils travaillent maintenant pour une très grande entreprise appelée Twitter. C'est la meilleure compagnie sur la planète.

Pourquoi cette conversation?

Pourquoi est-ce que je fais ce discours et tous les autres discours que j'ai? Je veux que vous essayiez Graal. Il y a beaucoup de raisons pour lesquelles je veux que vous essayiez ceci parce que, premièrement, je suis une personne très gentille. Je veux que vous économisiez de l'argent. Je pense que je fais une diapositive à ce sujet. J'explique en gros comment nous économisons de l'argent en utilisant Graal. Nous réduisons l'utilisation de la CPU pour ce que nous faisons, nous utilisons moins de machines pour tout ce que nous faisons, ce qui représente beaucoup d'argent.

Ensuite, j'aimerais corriger les bogues existants dans Graal et nous en avons trouvé un groupe. Ensuite, il y a une discussion à propos des bogues que nous avons trouvés et que je leur ai expliquée. Nous n'avons pas trouvé les bugs en deux ans. Ce dont nous avons besoin, c’est que nous devons lancer un code différent à Graal. Ce que j'aimerais, c'est que vous utilisiez votre code de production merdique et que vous l'exécutiez sur Graal, ce serait vraiment bien. Puisque vous avez tous convenu plus tôt que vous courez sur 11, ce n'est pas un problème.

Ensuite, je veux améliorer Graal, je veux en faire un meilleur compilateur. Nous ne pouvons améliorer le compilateur que si nous voyons des problèmes. Nous ne pouvons pas simplement optimiser dans le bleu, nous devons savoir: "Ce code ne fonctionne pas comme il se doit ou il ne fonctionne pas aussi bien que sur C2." Ensuite, nous examinons et pouvons réellement l’améliorer. C'est pour ça que je fais ça.

Ensuite, lorsque je fais mes présentations, les gens viennent me voir et me demandent: "Est-ce sûr de l'utiliser, car c'est un compilateur expérimental? Votre centre de données est-il en panne?" Non. Nous avons nos propres centres de données, ils sont toujours opérationnels. Vous pouvez tweeter tout de suite et vous verriez que cela fonctionne.

Comment utiliser Graal et où l'obtenir? C’est exactement pour cette raison que j’ai fait cet exposé pour ces deux questions. Ensuite, quand ils essaient réellement, ils m'envoient généralement un email, un tweet ou un DM. La plupart se plaignent des chiffres de référence et de ce que Graal est nul. La raison en est qu’ils ne comprennent pas la différence entre un compilateur écrit en C ++ et un compilateur écrit Graal. Ils regardent les chiffres qu'ils obtiennent dans le mauvais sens. Je vous explique maintenant pour que vous ne commettiez pas la même erreur.

C'est la chose d'économie d'argent. C'est ce qu'on appelle la quête de Twitter pour une exécution entièrement Graal. C'est essentiellement l'histoire de ma première année de travail sur Twitter, comment nous avons commencé à exploiter des services sur Graal, combien d'argent nous avons économisé. Non, je ne vous dis pas combien c'est parce que je ne suis pas autorisé à le faire, mais c'est beaucoup. C'est beaucoup plus que ce qu'ils me paient, ce que je trouve injuste, mais ils ne sont pas d'accord, je ne comprends pas. Regardez ceci si cela vous intéresse.

Utilisez-le démo

Retour à la démo. Nous avons déjà fait cela, montons. Comment l'utilisons-nous? Vous obtenez un JDK avec Graal. Si vous avez ce module, jdk.internal.vm.compiler, la seule chose à faire est de l'activer. Faisons une démo – comment l'allumer.

Nous allons ouvrir JDK puis JEP 243. C'est le JEP JVMCI dont je parlais et nous espérons que le Wi-Fi fonctionnera plus rapidement. Ce sont les problèmes dont je parlais. Je suis content de ne plus faire la démo dans le nuage car cela ne fonctionnerait pas. Je voulais vous montrer dans le texte du PEC que cela explique comment activer Graal ou lors du compilateur JVMCI. Ce pourrait être n'importe quel compilateur. S'il existe un compilateur implémentant l'API JVMCI, vous pouvez l'exécuter.

Il y en a un qui s'appelle "UnlockExperimentalVMOptions", car il s'agit toujours d'une fonctionnalité de machine virtuelle expérimentale. Ensuite, il y en a un qui s'appelle "EnableJVMCI". En gros, il active uniquement l'accès à l'API. Cela n'active pas automatiquement le compilateur JIT, mais vous donne accès à l'API. Parfois, si vous exécutez Truffle – je pense que Oracle Labs le fait parfois, ils fonctionnent en réalité sur C1 et C2 mais utilisent Graal pour Truffle. C'est pourquoi vous n'activez que JVMCI, mais pas le compilateur. Puis le dernier est UseJVMCICompiler, c’est tout ce dont vous avez besoin. Nous copions ceci et nous le collons dans cette option d’outil Java, puis si nous faisons une version java, nous verrons qu’il reprend tout cela, puis il l’imprimera.

Il y a une chose appelée PrintFlagsFinal. Il imprime tous les indicateurs de la machine virtuelle. Nous recherchons ceux qui ont JVMCI dans le nom et il y a comme un 10, 12 ou quelque chose. Comme vous pouvez le voir, nous avons ici EnablJVMCI et c’est vrai parce que nous l’avons allumé. Il suffit d’utiliser le compilateur JVMCI, c’est vrai parce que nous l’allumons. Ensuite, celle que je recherche est celle-ci, les propriétés d’impression JVMCI. Nous allons donc procéder, puis une très longue liste de propriétés est imprimée. La plupart d'entre eux sont liés à Graal, des choses que vous pouvez accorder avec Graal, des choses que vous pouvez changer et tout en haut, c'est comme une poignée de propriétés liées à JVMCI.

Celui que je cherche ici s'appelle InitTimer. Comme il s’agit d’une propriété Java, nous avons décidé de transmettre les options à JVMCI et à Graal en tant que propriétés Java, car elles sont toutes deux écrites en Java, ce qui est logique. Nous faisons un -D puis InitTimer et ensuite égal à true, évidemment parce que c'est comme ça que nous devons le faire. En fait, il affiche une sortie d'initialisation lorsque JVMCI s'initialise. Faisons cela. Rien ne s'est passé. Il n'y a pas de sortie de journal supplémentaire à l'exception de la version. Avons-nous fait quelque chose de mal? Non, nous n'avons pas. JVMCI est paresseusement initialisé.

Qu'est-ce qu'une compilation à plusieurs niveaux? Nous commençons par interpréter le bytecode Java, puis nous exécutons interprété, puis nous recompilons avec C1. Il existe en fait quatre niveaux de niveaux dans HotSpot et les trois premiers niveaux sont tous compilés par C1. Le nombre dépend de la quantité d'informations de profilage collectées. Nous compilons généralement au niveau trois où nous obtenons une grande quantité d’informations de profilage que nous utiliserons ensuite pour la recompilation de C2. Vous parcourez des niveaux et accélérez votre code à chaque étape. Ceci est la compilation de niveau. C2 est le niveau quatre et nous remplaçons C2 par Graal ici.

Si nous imprimons la compilation ici, vous verrez toutes les méthodes en cours de compilation lorsque vous créez une version avec tiret. Il exécute un peu de code Java, donc il compile des choses. La troisième colonne, celle-ci est le niveau de la compilation. Comme vous pouvez le constater, il n’ya pas quatre personnes. La raison en est qu’aucun code n’est suffisamment chaud pour déclencher une compilation de niveau quatre et c’est pourquoi JVMCI n’est pas initialisé. Qu'est-ce que nous devons faire, c'est que nous devons courir un peu plus.

Nous pouvons faire un tiret L qui, en gros, n’imprime que les points de repère du cadre. Si nous faisons cela ici, dans un délai d'initialisation, vous pouvez voir que quelque chose est en train de s'initialiser. Cela commence ici avec le runtime de classe HotSpot JVMCI, puis fait un tas de choses, obtenez une configuration pour notre architecture, MD 64 mais il ne semble pas que cela ait réellement terminé l'initialisation. C’est exact, car la liste des points de repère se termine plus tôt avant que JVMCI ne soit complètement initialisé et compose une méthode. Nous devons courir un peu plus.

Ce que nous faisons, c'est que nous exécutons un petit test de référence d'un test de référence appelé Aurora et ensuite vous pouvez tout initialiser. Nous finissons réellement. Comme vous pouvez le voir ici, à l'exécution du HotSpot JVMCI, il a fallu 56 millisecondes pour le faire. Ensuite, il y a une chose appelée fabrique de configuration du compilateur, qui sélectionne le compilateur. Comme je l’ai dit plus tôt, si vous en avez plusieurs, c’est les compilateurs qui supportent JVMCI, vous pouvez le sélectionner avec une propriété Java. Tout cela est décrit dans le PEC que je ne peux pas afficher car le Wi-Fi est en panne, mais vous pouvez le voir. Ensuite, par défaut, et puisqu'il n'y a qu'un seul concurrent, il sélectionne toujours Graal. Nous initialisons cette classe appelée runtime HotSpot Graal, effectue un tas de choses. Comme vous pouvez le constater, cela crée un back-end. Ensuite, il semble également que l'initialisation de cette opération n'est pas vraiment terminée. En effet, le faisceau de référence Aurora redirige la sortie vers un fichier. C'est quelque part maintenant dans un fichier, mais croyez-moi, ça se termine. Ce repère a été réalisé avec Graal.

Qu'est-ce que Bootstrapping?

Maintenant, nous devons parler de bootstrap. Le démarrage est toujours un problème. Oracle Labs s'est associé à Oracle, le groupe de plates-formes de voyage qui utilise Java. Il y a un projet appelé LIP Graal, nous ne l'avons pas encore. Je pense que la dernière version de GraalVM en contient, mais pas OpenJDK ou OracleJDK. LIP Graal utilise l’image native de la machine virtuelle pour compiler AOT en graal, ce qui est tout à fait logique. Ensuite, toute la partie amorçage disparaît et les éléments d'allocation de mémoire que nous verrons plus tard disparaîtront, mais pour le moment, nous devons gérer l'amorçage.

Graal est simplement une autre application Java exécutée sur votre machine virtuelle, écrite en Java, elle charge les classes Java, bien entendu. Ces classes Java ont des méthodes Java et ces méthodes – les propres méthodes de Graal doivent être compilées à un moment donné. Sinon, nous interpréterions notre compilateur, ce qui serait ridiculement lent. Nous devons le compiler, c'est le bootstrap. Faisons cela.

Démo Bootstrap

Vous pouvez faire un bootstrap explicite comme celui-ci, Bootstrap JVMCI. S'il vous plaît ne faites pas cela. C'est vraiment juste pour des fins de faire une présentation. Parfois, il peut être utile de procéder à des analyses comparatives, mais ne le faites pas, cela fausserait tout. Faisons une bande ascendante ici. Comme vous pouvez le constater, chaque point correspond à une centaine de compilations de méthodes et s’accélère. Les points apparaissent plus rapidement parce que Graal est compilé par lui-même et peut ensuite compiler le code plus rapidement. Ca a du sens. Nous avons compilé 2500 méthodes en 19 secondes. Personne ne veut attendre 18 secondes pour que ce putain de truc Java apparaisse. Je sais que personne n'écrit LS en Java, mais si quelqu'un écrit LS, 18 secondes – probablement pas.

L'amorçage peut être fait explicitement ou implicitement en arrière-plan. Vous savez que chaque machine virtuelle Java a des threads GC. Vous savez peut-être que, il a un tas de threads où il fait la collecte des ordures en parallèle. Il en va de même pour les compilations, il a les threads du compilateur et les threads du compilateur, ils font le travail en arrière-plan. Vous interprétez toujours votre code, vous exécutez vos fichiers, peu importe ce que c'est, et en arrière-plan, vous compilez du code. Une fois que cela est fait, vous exécutez ensuite le code compilé.

Nous courons à nouveau la référence. Nous exécutons trois itérations de cette référence Aurora ici avec C2. Cela prend 2,9 secondes – disons trois secondes. Si nous faisons la même chose ici avec Graal, vous pouvez voir que la première manche prend un peu plus longtemps qu'avec C2 – comme cinq secondes. Ensuite, les deuxième et troisième manches sont plus rapides, ce qui est surprenant. Le repère lui-même est un peu floconneux mais la performance est à peu près la même. Nous utilisons la différence entre le premier passage, la différence d'une seconde étant donné que nous devons compiler Graal. Ce n'est pas 18 secondes, c'est fondamentalement un.

Nous sur Twitter, nous le courons de cette façon. Nous faisons le bootstrap, nous ne compilons PAS AOT Graal ou quoi que ce soit car vous ne compilez qu'un nombre limité de méthodes pour Graal. Cela ne devient pas plus. Si votre application est plus grande, il ne reste qu'une seconde. Je suis sûr que le démarrage de toutes vos applications prend plus de deux secondes ou une seconde. Si c'est une seconde de plus, ce n'est pas grave.

Ce que nous avons appris

Bootstrapping compile pas mal de méthodes. Si vous utilisez un système à plusieurs niveaux, ce que nous venons de faire correspond à environ 2 500. Si vous désactivez le mode multiniveau, cela signifie que Graal doit en compiler davantage car C1 ne fait pas partie de la liste. En fait, il compile environ 5 000 et 5 000 méthodes, ce que vous verrez lorsque vous exécutez une grosse application. Ensuite, vous compilez environ 5 000 méthodes de Graal, mais les frais généraux ne sont vraiment pas perceptibles.

Ensuite, vous pouvez le faire soit au début – ne le faites pas – ou à la demande pendant l'exécution. C'est ce que nous venons de voir. Par défaut, Graal compile à la demande, les méthodes Graal elles-mêmes ne sont compilées qu'avec C1. La raison en est que nous ne voulons pas que les compilations des méthodes Graal concourent avec les méthodes de notre application. Pour les méthodes Graal, nous voulons du code aussi rapidement que possible pour qu'il compile notre application. Vous pouvez désactiver ceci avec un drapeau.

Démo Java Heap

L'utilisation du tas Java est également très importante. Graal est écrit en Java, ce qui signifie, comme je l’ai dit au tout début, que nous venons d’apprendre que les méthodes Graal ne sont compilées que par C1, donc ce n’est pas un problème, mais toutes les méthodes en cours de compilation pour votre application utilisent la mémoire heap Java. Peut-être, méthodes Graal aussi. C'est le drapeau où vous pouvez l'activer et le désactiver. Faisons ici une rapide démonstration du tas Java.

Nous utilisons à nouveau ce repère. Nous allumons. Nous exécutons les trois itérations d’Aurora et le harnais de référence permet de réaliser un GC système avant et après une itération de référence. La raison en est que cela nettoie le tas. Il se débarrasse de toutes les choses. Comme vous pouvez le constater, il n’existe pas de GC au cours de l’évaluation. Aurora est un benchmark très intense en calcul, il ne fait pas beaucoup d’allocations de mémoire. Nous avons environ 39 mégaoctets sur le tas après une analyse, puis nous collectons jusqu'à 1. Cela n'alloue pas beaucoup.

Si nous faisons la même chose ici avec Graal, vous pouvez déjà voir qu'il se passe plus de choses parce que des GC sont en cours lors de notre première itération. Nous avons celui-ci ici, nous avons alloué environ 130 Mo, puis nous en avons descendu à 7, un autre 35 35-ish à 8, puis il reste 86 mégaoctets sur le tas après la course. C'est Graal qui fait son travail. C'est Graal qui compile les méthodes de référence.

Comme vous pouvez le constater, à la deuxième itération, il n’y avait pas de GC au cours de l’évaluation. Nous avions environ 130 mégaoctets après la course sur le tas. Cela signifie que nous étions encore en train de compiler certaines méthodes, mais après la troisième itération, nous ne compilons plus. Toutes les méthodes de référence sont compilées, c'est tout. C'est la raison pour laquelle seule la première itération est plus lente, car cela fonctionne, les GC, le ralentit un peu, mais vous avez terminé.

Je soutiens que lorsque vous démarrez ce que vous avez si vous avez un microservice, une application ou quoi que ce soit d'autre, cela prendra un certain temps avant que cette chose ne se produise. Presque toutes les compilations de votre application dépendent évidemment de la taille, mais elles se produisent presque toutes dans les 30 premières secondes, la première minute, voire les deux premières minutes. Ensuite, rarement parsemé de quelques compilations mais la majorité se fait au tout début. À ce moment-là, votre application n'utilise même pas toute la mémoire de mémoire Java, car elle n'est même pas encore totalement opérationnelle. Si vous vivez dans un monde de microservices, celui-ci doit se connecter à un billion d'autres connexions réseau de microservices, peut-être qu'il fait un peu une boucle d'échauffement, puis à ce stade, tout est compilé et vous êtes prêt à accepter les demandes de production. .

Le fait que Graal utilise votre mémoire Java n'est pas vraiment vrai. Il y a en fait un avantage ici et je discutais avec les gens d'Oracle que LIP Graal enlève cet avantage. Dans un monde en nuage, et nous vivons tous dans un monde en nuage aujourd'hui, vous payez essentiellement pour la mémoire. Vous connaissez les métadonnées, vous devez réserver un peu de mémoire. Si vous avez un conteneur cloud de huit gigaoctets, vous ne pouvez pas organiser huit tas de votre mémoire Java, vous le savez tous, car il existe sur le site une mémoire native supplémentaire nécessaire à la JVM. L'un de ces problèmes, et vous n'y avez jamais prêté attention, est que les compilateurs JIT ont besoin de mémoire pour compiler des choses.

Si vous ne laissez pas assez de mémoire sur le côté, vous risquez de faire tuer votre conteneur car le compilateur utilise trop de mémoire. C'est le drastique que j'ai jamais vu. Ce n'est pas normal, mais la compilation la plus folle que nous ayons jamais vue chez Oracle était une compilation C2 qui utilisait un gigaoctet de mémoire car elle était énorme, elle optimisait beaucoup les boucles et rendait les graphiques de compilation très volumineux. Comme je l'ai dit, ce n'est pas normal. La taille normale des compilations pour l'allocation de mémoire est de l'ordre de 10 mégaoctets ou 20-30; les grandes peuvent atteindre 100, mais vous devez réserver cette mémoire sur le site. Si vous n'utilisez pas C2, vous pouvez techniquement prendre cette mémoire et la donner au tas Java, car vous avez alors un peu plus de tas Java et au tout début, Graal l'utilisait, puis vous disposiez de plus de mémoire pour votre application. . C'est un avantage mais ça va disparaître, je pense.

Qu'avons-nous appris? Graal utilise la mémoire heap Java pour effectuer les compilations. Il n'y a pas encore d'isolement de tas. C'est la chose LIP Graal dont je parlais. La majeure partie de la mémoire utilisée par Graal est au démarrage. Comme je l'ai dit, la plupart des compilations se produisent au début, lorsque votre application n'est pas encore complètement prête. Rappelez-vous que la mémoire est utilisée quand même. Il s’agit de la mémoire malloc ou du tas Java, mais vous ne pouvez pas y échapper. Nous avons besoin de mémoire pour faire les compilations.

Construire une démo

Ce que je ferai, c’est, je clonerai mon truc local, nous clonerons Graal. Ensuite, nous avons besoin de quelque chose appelé MX. C'est un script qu'Oracle Labs utilise pour tout. Il peut cloner le code, le construire, exécuter le test, créer des fichiers de configuration pour votre ID, tout faire. Je ne sais même pas quelle est sa taille maintenant, c'est plus de 10 000 lignes de code Python. Je veux vomir sur scène. Je me plains tellement de fois à ce sujet, mais ça ne va pas disparaître. Si vous voulez exécuter Bleeding Edge, vous en avez besoin.

J'aurais besoin de mettre MX sur mon chemin parce que vous devez l'exécuter. C'est la seule fois où je triche parce que je manque de temps. J'ai déjà MX sur mon chemin. Je vais désinstaller très rapidement les options de l'outil Java afin que nous n'obtenions pas tous ces résultats. Ensuite, la seule chose à faire est la construction MX. Je mets Java à la maison, il s’agit du JDK 11. Je pense qu’il l’imprime même qu’il le capte et le construit maintenant. Je ne peux pas tirer la dernière version, mais je l'ai tirée avant de venir à QCon dans ma chambre d'hôtel. C'est à partir d'aujourd'hui, c'est la dernière chose.

Attendons cela, cela prend quelques minutes. Permettez-moi de vous montrer entre-temps Xlog: charges de classe +, et le point de repère, puis à nouveau le problème Aurora, et nous prenons GraalVM. Comme vous pouvez le constater, lorsque nous exécutons ceci et que nous enregistrons toute la charge de classe, nous voyons toutes ces classes Graal être chargées. Ils sont chargés de cette chose. JRT est comme le système de fichiers que le JDK utilise en interne pour charger des fichiers à partir de modules. Il charge les codes, le code Graal de ce module, que nous avons vu auparavant. jdk.internal.vm.compiler, c'est celui fourni avec OpenJDK.

Nous attendons que ce compilateur se termine ici, il compile un tas de choses. Vous pouvez également voir que la compilation est Truffle. Nous voulons seulement une chose qui s'appelle Archivage Graal. Ensuite, compilateur GraalVM Graal. La VM MX n’exécute que la VM avec la version Graal que nous venons de construire. Nous pouvons faire mx vm- version ici. Cela devrait fonctionner parce que je pense que la compilation est terminée. Il imprime des trucs et je peux ensuite faire un discours, en imprimer un tas de plus. Ignorez les éléments en haut, c’est l’importante ligne qui utilise le JDK 11. Ensuite, comme vous pouvez le constater, elle insère des choses ici, améliore le chemin du module jusqu’à ce type, qui est essentiellement une Truffle modulaire qui a été construite. C'est le graphique que nous venons de construire ici, à gauche.

Nous utilisons maintenant la dernière version de Graal. Si nous faisons ce type avec MX VM et Graal, les fichiers de classe Graal, ils sont maintenant chargés à partir d'un fichier appelé Graal.jar. Vous pouvez réellement voir que la dernière version de Graal que nous venons de construire a été reprise et que le logiciel fonctionne. Permettez-moi de supprimer l'enregistrement ici et d'exécuter trois itérations de ce type. J'espère que chaque fois que je fais ça sur scène, c'est plus rapide qu'auparavant, mais ce n'est jamais le cas, car l'Aurora ne l'est pas. Nous ne pouvons plus rien faire à ce sujet. Vous voyez que c'est cinq secondes, la première puis 5.2, 5.6. C'est là où nous en avions aussi plus tôt.

C’est aussi simple que d’obtenir Graal, de le construire, puis de jouer avec. Vous pouvez utiliser MX pour créer la configuration de l'ID, la charger dans votre ID préféré – j'espère que c'est Eclipse – pour pouvoir jouer. Fais ce que tu veux. C'est tellement facile parce que c'est Java. Vous changez quelque chose, vous enregistrez, puis vous courez avec. Vous n'avez même pas besoin de recompiler votre JDK. C'est incroyable.

Démo Scala

C'était la démo. Je ne peux pas faire cette démo de production car A, je manque de temps et B, ça ne se construit pas, alors je vais l'ignorer. Je veux faire une démo de Scala cependant.

Pour celui-ci, nous revenons ici, puis nous définissons l'option d'outil Java à nouveau, mais nous augmentons la taille de notre segment de mémoire à deux gigaoctets. La raison en est que, sinon, nous avons trop de GC. Faisons un point de repère de taille par défaut et nous effectuons deux itérations, ce qui devrait suffire, d’un repère appelé factorie. Permettez-moi de parler de cela ici avec C2, puis nous faisons la même chose ici et nous attendons.

Banc Scala. C’est le fichier de référence que j’utilise depuis le début. Il y a une page avec tous les points de repère dont elle dispose et celle-ci, appelée factorie, est celle que nous exécutons actuellement. Il dit: «C’est une boîte à outils pour la modélisation probabiliste déployable permettant d’extraire des sujets utilisant l’allocation de Dirichlet latent. Je ne sais pas du tout de quoi il s’agit. C’est un très bon exemple de ce que je veux vous montrer. J'ai donné cette présentation une fois. et après ma conversation, un type est venu me voir et m'a dit: "Nous utilisons LDA dans mon entreprise." J'ai dit: "Quoi?", c'est LDA, le truc latent, ils l'utilisent réellement. Je ne sais pas pourquoi Peu importe, j’ai oublié quelque chose de très important: nous devons verrouiller GC, sinon nous ne voyons pas ce qui se passe.

Vous pouvez voir qu'il en alloue environ 600. Sa taille augmente légèrement, mais 650, 680 mégaoctets par GC et nous effectuons 2 itérations car la première construit des structures de données internes et la seconde est un peu plus proche de la vérité. . Cela a pris 20 secondes pour exécuter ce test, laissez-moi commencer par ici pendant que je parle de xlog: gc. Il a fallu 20 secondes pour effectuer cette itération de référence et nous avions à peu près – vous pouvez voir 37 et 64, donc pas tout à fait 30 cycles GC. Oh bon sang. La taille du tas est trop petite.

Attendons ce gars. Comme vous pouvez le constater, la première itération avec C2 ici a pris 22 ou 23 secondes et a effectué autant de GC. Vous pouvez déjà voir que la première itération ici a été beaucoup plus rapide et a fait moins de GC. Attendons la deuxième itération. Celui-ci a pris 20 secondes pour courir et celui-ci a pris 16 et nous avons fait 32 ou 53 – seulement 20 GC. I'm not actually sure what is happening, it usually cuts GCs in half. The reason for this is the way Graal compiles code. It has something called escape analysis. That's an optimization, I'm not going to explain it now, it has a better escape analysis implementation than C2. Escape analysis can get rid of temporary object allocations. This benchmark is written in Scala and Scala allocates all these temporary objects all the time. Graal, the compiler can very well optimize that code. That's also why we at Twitter, save so much money because pretty much all of our microservices except a handful, are written in Scala.

We don't do as much GCs that reduces GC cycles, user CPU time, we reduce CPU utilization with that. That's what I wanted to show you. This benchmark is not really representative. It's the best one that's out there but I picked it because I want to look cool on stage. I'm not picking one that's 1% better.

Sommaire

The summary of this talk it's the summary of all of my talks and I know I'm over time, but it's very simple. That's all, I want you to try it. This is all you have to do if you have JDK 10 or later, which I know is an issue because we at Twitter, we also run on eight. You can download an 8 version from Oracle which is GraalVM basically. If you download GraalVM, the community edition, it's what I showed you today because the community edition has the Graal version that's on GitHub as open source. If you're on 8, download that one, please try it. Please let us know how it works. If it works better for you, I'm very happy for you. Tweet it out. If it crashes, that would be amazing because I want you to find a bug. I want you to find the bug and not us, because if Twitter is down because of a compiler bug, my life is in hell. I'm here right now. Give it a shot, let us know how it works. If you run something and it's faster, excellent, it's great. If it's slower, also let us know. What I said earlier, we would like to figure out what it is. Maybe we can do something about it.

See more presentations with transcripts

Click to rate this post!
[Total: 0 Average: 0]

Commentaires

Laisser un commentaire

Votre commentaire sera révisé par les administrateurs si besoin.