{"id":35851,"date":"2019-10-31T22:07:03","date_gmt":"2019-10-31T19:07:03","guid":{"rendered":"https:\/\/prohoster.info\/blog\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java\/"},"modified":"2019-10-31T22:07:03","modified_gmt":"2019-10-31T19:07:03","slug":"bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java","status":"publish","type":"post","link":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java","title":{"rendered":"Grande interview avec Cliff Click \u2014 le p\u00e8re de la compilation JIT en Java","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Grande interview avec Cliff Click \u2014 le p\u00e8re de la compilation JIT en Java\" src=\"\/wp-content\/uploads\/2019\/07\/9ea9740ef74c0ae14d334482af115222.png\" style=\"display:block;margin: 0 auto;\" \/><strong>Cliff Click<\/strong> \u2014 CTO de Cratus (capteurs IoT pour am\u00e9liorer les processus), fondateur et cofondateur de plusieurs startups (y compris Rocket Realtime School, Neurensic et H2O.ai) avec plusieurs sorties r\u00e9ussies. Cliff a \u00e9crit son premier compilateur \u00e0 15 ans (Pascal pour TRS Z-80)! Il est surtout connu pour son travail sur C2 en Java (the Sea of Nodes IR). Ce compilateur a montr\u00e9 au monde que le JIT pouvait produire du code de qualit\u00e9, ce qui a \u00e9t\u00e9 un des facteurs contribuant \u00e0 faire de Java l'une des principales plates-formes logicielles modernes. Par la suite, Cliff a aid\u00e9 l'entreprise Azul Systems \u00e0 construire un mainframe \u00e0 864 c\u0153urs avec un logiciel \u00e9crit en Java pur, qui maintenait des pauses GC sur un tas de 500 Go en moins de 10 millisecondes. En g\u00e9n\u00e9ral, Cliff a eu l'occasion de travailler sur tous les aspects de la JVM.<br clear=\"all\"><br \/>\n\u00a0<br \/>\nCet article sur Habr est une grande interview avec Cliff. Nous allons aborder les sujets suivants :<\/p>\n<p><\/p>\n<ul>\n<li>Passer aux optimisations de bas niveau<\/li>\n<li>Comment effectuer un grand refactoring<\/li>\n<li>Mod\u00e8le de co\u00fbt<\/li>\n<li>Apprendre les optimisations de bas niveau<\/li>\n<li>Exemples pratiques d'am\u00e9lioration de la performance<\/li>\n<li>Pourquoi cr\u00e9er son propre langage de programmation<\/li>\n<li>Carri\u00e8re d'ing\u00e9nieur en performance<\/li>\n<li>D\u00e9fis techniques<\/li>\n<li>Un peu sur l'allocation des registres et le multithreading<\/li>\n<li>Le plus grand d\u00e9fi de la vie<\/li>\n<\/ul>\n<p><\/p>\n<p>L'interview est conduite par :<\/p>\n<p><\/p>\n<ul>\n<li><strong>Andrey Sataryan<\/strong> de Amazon Web Services. Dans sa carri\u00e8re, il a travaill\u00e9 sur des projets tr\u00e8s vari\u00e9s : il a test\u00e9 une base de donn\u00e9es distribu\u00e9e NewSQL chez Yandex, un syst\u00e8me de d\u00e9tection dans le cloud au sein de Kaspersky Lab, un jeu multijoueur chez Mail.ru et un service de calcul des prix des devises chez Deutsche Bank. Il s'int\u00e9resse aux tests de syst\u00e8mes back-end \u00e0 grande \u00e9chelle et distribu\u00e9s.<\/li>\n<li><strong>Vladimir Sitnikov<\/strong> de Netcracker. Il travaille depuis dix ans sur la performance et l'\u00e9volutivit\u00e9 de NetCracker OS \u2014 un logiciel utilis\u00e9 par les op\u00e9rateurs de t\u00e9l\u00e9communications pour automatiser les processus de gestion des r\u00e9seaux et du mat\u00e9riel r\u00e9seau. Il s'int\u00e9resse aux questions de performance de Java et d'Oracle Database. Il est l'auteur de plus d'une douzaine d'am\u00e9liorations de la performance dans le pilote JDBC PostgreSQL officiel.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"perehod-k-nizkourovnevym-optimizaciyam\">Passer aux optimisations de bas niveau<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Vous \u00eates une personne reconnue dans le monde de la compilation JIT, en Java et dans le domaine de la performance en g\u00e9n\u00e9ral, n'est-ce pas?\u00a0<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: C'est exactement \u00e7a!<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Commen\u00e7ons par des questions g\u00e9n\u00e9rales sur le travail sur la performance. Que pensez-vous du choix entre les optimisations de haut niveau et de bas niveau, comme le travail au niveau du CPU?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Ici, tout est simple. Le code le plus rapide est celui qui ne s'ex\u00e9cute jamais. Il est donc toujours n\u00e9cessaire de commencer par un niveau \u00e9lev\u00e9 et de travailler sur les algorithmes. Une meilleure notation O bat une moins bonne notation O, sauf si des constantes suffisamment grandes interviennent. Les \u00e9l\u00e9ments de bas niveau sont les derniers \u00e0 \u00eatre pris en compte. En g\u00e9n\u00e9ral, si vous avez optimis\u00e9 tout le reste de la pile correctement et qu'il reste encore quelque chose d'int\u00e9ressant, c'est \u00e0 ce moment-l\u00e0 que vous atteignez le niveau bas. Mais comment commencer par un niveau \u00e9lev\u00e9 ? Comment savoir que vous avez fait suffisamment de travail \u00e0 un niveau \u00e9lev\u00e9 ? Eh bien\u2026 il n'y a pas de recettes toutes faites. Il faut comprendre le probl\u00e8me, d\u00e9cider ce que vous allez faire (pour ne pas faire des \u00e9tapes inutiles par la suite), et c'est alors que vous pouvez d\u00e9ployer un profileur qui peut dire quelque chose d'utile. \u00c0 un certain moment, vous r\u00e9alisez vous-m\u00eame que vous vous \u00eates d\u00e9barrass\u00e9 des \u00e9l\u00e9ments inutiles et qu'il est temps de se concentrer sur le r\u00e9glage fin du bas niveau. C'est sans aucun doute un art particulier. Beaucoup de gens font des choses inutiles, mais avancent si vite qu'ils n'ont pas le temps de se soucier de la performance. C'est jusqu'\u00e0 ce que la question se pose. En g\u00e9n\u00e9ral, 99% du temps, personne ne s'int\u00e9resse \u00e0 ce que je fais, jusqu'\u00e0 ce qu'une chose critique apparaisse sur le chemin, une chose \u00e0 laquelle quelqu'un pourrait se soucier. Et c'est l\u00e0 que tout le monde commence \u00e0 vous critiquer sur pourquoi \u00e7a ne fonctionnait pas parfaitement d\u00e8s le d\u00e9part. En gros, il y a toujours quelque chose \u00e0 am\u00e9liorer dans la performance. Mais 99% du temps, vous n'avez pas d'indices ! Vous essayez juste de faire en sorte que quelque chose fonctionne et, dans ce processus, vous comprenez ce qui est important. On ne peut jamais savoir \u00e0 l'avance que ce morceau doit \u00eatre parfait, donc, en fait, il faut \u00eatre parfait dans tout. Et c'est impossible et vous ne le faites pas. Il y a toujours plein de choses \u00e0 r\u00e9parer - et c'est tout \u00e0 fait normal.<\/p>\n<p><\/p>\n<h1 id=\"kak-delat-bolshoy-refaktoring\">Comment effectuer un grand refactoring<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Comment travaillez-vous sur la performance ? C'est un probl\u00e8me transversal. Par exemple, avez-vous d\u00e9j\u00e0 d\u00fb traiter des probl\u00e8mes r\u00e9sultant de l'interaction d'une grande quantit\u00e9 de fonctionnalit\u00e9s d\u00e9j\u00e0 existantes ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: J'essaie d'\u00e9viter cela. Si je sais que la performance va poser probl\u00e8me, je r\u00e9fl\u00e9chis avant de commencer \u00e0 coder, surtout concernant les structures de donn\u00e9es. Mais souvent, on d\u00e9couvre tout cela beaucoup plus tard. Et alors, il faut prendre des mesures extr\u00eames et faire ce que j'appelle \u00ab r\u00e9\u00e9crire et r\u00e9gner \u00bb : il faut s'emparer d'un assez grand morceau. Une partie du code devra tout de m\u00eame \u00eatre r\u00e9\u00e9crite \u00e0 cause de probl\u00e8mes de performance ou pour d'autres raisons. Quelle que soit la raison qui pousse \u00e0 r\u00e9\u00e9crire le code, il est presque toujours pr\u00e9f\u00e9rable de r\u00e9\u00e9crire un plus grand morceau plut\u00f4t qu'un plus petit. \u00c0 ce moment-l\u00e0, tout le monde commence \u00e0 trembler de peur : \u00ab Oh mon dieu, on ne peut pas toucher autant de code ! \u00bb. Mais, en r\u00e9alit\u00e9, cette approche fonctionne presque toujours beaucoup mieux. Il faut s'attaquer \u00e0 un gros probl\u00e8me d\u00e8s le d\u00e9part, tracer un grand cercle autour de lui et dire : tout ce qui se trouve \u00e0 l'int\u00e9rieur du cercle, je vais le r\u00e9\u00e9crire. La fronti\u00e8re est beaucoup plus petite que le contenu \u00e0 l'int\u00e9rieur, qui doit \u00eatre remplac\u00e9. Et si ce contour permet de travailler parfaitement \u00e0 l'int\u00e9rieur \u2013 tu es libre, fais ce que tu veux. Une fois que tu as compris le probl\u00e8me, le processus de r\u00e9\u00e9criture devient beaucoup plus simple, alors n'h\u00e9site pas \u00e0 prendre un gros morceau !<br \/>\nEn m\u00eame temps, lorsque tu fais une r\u00e9\u00e9criture en gros et que tu r\u00e9alises que la performance sera un probl\u00e8me, tu peux commencer \u00e0 t'en pr\u00e9occuper tout de suite. Cela se transforme g\u00e9n\u00e9ralement en choses simples comme \u00ab ne copie pas les donn\u00e9es, g\u00e8re les donn\u00e9es aussi simplement que possible, fais-les plus petites \u00bb. Dans de grandes r\u00e9\u00e9critures, il existe des m\u00e9thodes standard pour am\u00e9liorer la performance. Et elles tournent presque toujours autour des donn\u00e9es.<\/p>\n<p><\/p>\n<h1 id=\"model-stoimosti\">Mod\u00e8le de co\u00fbt<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Dans l'un des podcasts, vous parliez des mod\u00e8les de co\u00fbt en lien avec la performance. Pouvez-vous expliquer ce que cela signifie ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Bien s\u00fbr. Je suis n\u00e9 \u00e0 une \u00e9poque o\u00f9 la performance du processeur \u00e9tait d'une importance cruciale. Et cette \u00e8re revient \u2013 le destin n'est pas exempt d'ironie. J'ai commenc\u00e9 \u00e0 vivre \u00e0 une \u00e9poque de machines \u00e0 huit bits, mon premier ordinateur fonctionnait avec 256 octets. Oui, des octets. Tout \u00e9tait tr\u00e8s petit. Il fallait compter les instructions, et d\u00e8s que nous avons commenc\u00e9 \u00e0 progresser dans les langages de programmation, les langages prenaient de plus en plus en charge. Il y avait l'assembleur, puis le Basic, puis le C, et le C s'occupait de nombreux d\u00e9tails, comme la r\u00e9partition des registres et le choix des instructions. Mais tout cela \u00e9tait assez clair, et si j'avais un pointeur sur une instance de variable, alors j'obtiendrais un chargement, et le co\u00fbt de cette instruction est connu. Le mat\u00e9riel fournit un nombre connu de cycles machine, donc la vitesse d'ex\u00e9cution de diff\u00e9rentes t\u00e2ches peut \u00eatre calcul\u00e9e simplement en additionnant toutes les instructions que vous pr\u00e9voyez d'ex\u00e9cuter. Chaque compare\/test\/branche\/appel\/chargement\/storation pouvait \u00eatre additionn\u00e9e et vous pouviez dire : voil\u00e0 le temps d'ex\u00e9cution. En cherchant \u00e0 am\u00e9liorer la performance, vous remarquerez certainement ceux qui correspondent aux petits cycles chauds.\u00a0<br \/>\nMais d\u00e8s que vous passez \u00e0 Java, Python et des choses similaires, vous vous \u00e9loignez tr\u00e8s rapidement du mat\u00e9riel bas niveau. Quel est le co\u00fbt d'un appel getter en Java ? Si le JIT dans HotSpot a tout correctement <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.openjdk.java.net\/display\/HotSpot\/Inlining\">inlin\u00e9<\/a><\/noindex>, ce sera un chargement, mais s'il ne le fait pas \u2013 ce sera un appel de fonction. Comme l'appel se trouve dans une boucle chaude, il annulera toutes les autres optimisations dans cette boucle. Par cons\u00e9quent, le co\u00fbt r\u00e9el sera bien plus \u00e9lev\u00e9. Et vous perdez imm\u00e9diatement la capacit\u00e9 de regarder un morceau de code et de comprendre ce qu'il vaut d'ex\u00e9cuter en termes de fr\u00e9quence d'horloge du processeur, de m\u00e9moire utilis\u00e9e et de cache. Tout cela devient int\u00e9ressant seulement si vous vous plongez r\u00e9ellement dans la performance.<br \/>\nNous nous trouvons dans une situation o\u00f9 la vitesse des processeurs n'a quasiment pas augment\u00e9 depuis une d\u00e9cennie. Les temps anciens reviennent ! Vous ne pouvez plus compter sur une bonne performance \u00e0 un seul fil. Mais si jamais vous vous lancez dans le calcul parall\u00e8le \u2013 c'est incroyablement complexe, tout le monde vous regarde comme si vous \u00e9tiez James Bond. Des acc\u00e9l\u00e9rations d\u00e9cupl\u00e9es se produisent g\u00e9n\u00e9ralement l\u00e0 o\u00f9 quelqu'un a manqu\u00e9 quelque chose. La parall\u00e9lisation demande beaucoup de travail. Pour obtenir cette fameuse acceleration d\u00e9cupl\u00e9e, il faut comprendre le mod\u00e8le de co\u00fbt. Ce qui co\u00fbte quoi et combien. Et pour cela, il faut comprendre comment le langage s'int\u00e8gre au mat\u00e9riel sous-jacent.<br \/>\nMartin Thompson a trouv\u00e9 un excellent mot pour son blog <noindex><a rel=\"nofollow\" href=\"https:\/\/mechanical-sympathy.blogspot.com\/\">Sympathie M\u00e9canique<\/a><\/noindex>! Il est essentiel de comprendre ce que le mat\u00e9riel s'appr\u00eate \u00e0 faire, comment il va le faire, et pourquoi il fait ce qu'il fait. En utilisant cela, il est assez simple de commencer \u00e0 compter les instructions et de d\u00e9couvrir o\u00f9 le temps d'ex\u00e9cution s'en va. Si vous n'avez pas la formation appropri\u00e9e, vous cherchez juste un chat noir dans une pi\u00e8ce sombre. Je vois constamment des gens optimiser la performance, qui n'ont aucune id\u00e9e de ce qu'ils font r\u00e9ellement. Ils souffrent beaucoup et n'avancent que tr\u00e8s peu. Et quand je prends le m\u00eame morceau de code, j'y ajoute quelques petits hacks et je r\u00e9alise un acc\u00e9l\u00e9ration de cinq ou dix fois, ils disent : eh bien, ce n'est pas juste, on savait d\u00e9j\u00e0 que tu \u00e9tais meilleur. Incroyable. De quoi s'agissait-il... le mod\u00e8le de co\u00fbt \u2013 c\u2019est une question de quel code vous \u00e9crivez et \u00e0 quelle vitesse il fonctionne en moyenne dans le grand sch\u00e9ma.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Et comment garder un tel volume en t\u00eate ? Cela s'acquiert avec beaucoup d'exp\u00e9rience, non ? O\u00f9 trouve-t-on cette exp\u00e9rience ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Eh bien, mon exp\u00e9rience, je l'ai acquise de mani\u00e8re pas tr\u00e8s simple. J'ai programm\u00e9 en Assembleur \u00e0 une \u00e9poque o\u00f9 il \u00e9tait possible de comprendre chaque instruction s\u00e9par\u00e9ment. Cela peut sembler absurde, mais depuis, j'ai dans ma t\u00eate, dans ma m\u00e9moire, un ensemble d'instructions Z80 qui restera \u00e0 jamais. Je ne me souviens pas des noms des gens une minute apr\u00e8s la conversation, mais je me souviens du code \u00e9crit il y a 40 ans. C'est dr\u00f4le, cela ressemble au syndrome de \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A1%D0%B8%D0%BD%D0%B4%D1%80%D0%BE%D0%BC_%D1%81%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0\">l'\u00e9rudit idiot<\/a><\/noindex>\u00bb.<\/p>\n<p><\/p>\n<h1 id=\"obuchenie-nizkourovnevym-optimizaciyam\">Apprendre les optimisations de bas niveau<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Y a-t-il un moyen plus simple d'entrer dans le domaine ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Oui et non. Le mat\u00e9riel que nous utilisons tous n'a pas vraiment chang\u00e9 au fil des ans. Tout le monde utilise x86, \u00e0 l'exception des smartphones qui fonctionnent avec Arm. Si tu ne te lances pas dans un d\u00e9veloppement embarqu\u00e9 hardcore, tu as la m\u00eame chose. Bien, continuons. Les instructions n'ont pas beaucoup chang\u00e9 non plus au fil des si\u00e8cles. Il faut aller \u00e9crire quelque chose en Assembleur. Un peu, mais suffisamment pour commencer \u00e0 comprendre. Vous souriez, mais je parle tr\u00e8s s\u00e9rieusement. Il est important de comprendre la correspondance entre le langage et le mat\u00e9riel. Ensuite, il faut s'asseoir, \u00e9crire un peu et cr\u00e9er un petit compilateur pour un petit langage. \u00ab Petit \u00bb signifie qu'il doit \u00eatre r\u00e9alis\u00e9 dans un d\u00e9lai raisonnable. Il peut \u00eatre super simple, mais il doit g\u00e9n\u00e9rer des instructions. L'acte de g\u00e9n\u00e9ration d'instructions permettra de comprendre le mod\u00e8le de co\u00fbt pour le passage entre le code de haut niveau, sur lequel tout le monde travaille, et le code machine qui s'ex\u00e9cute sur le mat\u00e9riel. Cette correspondance s'ancrera dans nos esprits au moment de la r\u00e9daction du compilateur. M\u00eame d'un compilateur tr\u00e8s simple. Apr\u00e8s cela, on peut commencer \u00e0 regarder Java et le fait que son foss\u00e9 s\u00e9mantique est beaucoup plus profond, rendant la construction de ponts bien plus complexe. En Java, il est bien plus difficile de comprendre si notre pont est bon ou mauvais, ce qui va le faire s'effondrer ou non. Mais tu as besoin d'un point de d\u00e9part lorsque tu examines le code et comprends : \u00ab ah, ce getter doit \u00eatre inlin\u00e9 \u00e0 chaque fois \u00bb. Et ensuite, il s'av\u00e8re que cela se produit parfois, sauf lorsque la m\u00e9thode devient trop grosse, et que le JIT commence \u00e0 inliner tout. La performance de ces endroits peut \u00eatre pr\u00e9dite instantan\u00e9ment. En g\u00e9n\u00e9ral, les getters fonctionnent bien, mais ensuite tu observes de grandes boucles chaudes et r\u00e9alises qu'il y a des appels de fonctions et qu'on ne sait pas ce qu'elles font. C'est le probl\u00e8me avec l'utilisation g\u00e9n\u00e9ralis\u00e9e des getters, la raison pour laquelle ils ne s'inlinent pas - on ne sait pas si c'est un getter. Si tu as une base de code super petite, tu peux simplement te souvenir et dire : voici un getter, et voici un setter. Dans une grande base de code, chaque fonction a sa propre histoire, qui, au fond, n'est connue de personne. Le profileur dit que nous avons perdu 24 % de temps sur une boucle, et pour comprendre ce que fait cette boucle, il faut examiner chaque fonction \u00e0 l'int\u00e9rieur. Il est impossible de comprendre cela sans \u00e9tudier la fonction, et cela ralentit s\u00e9rieusement le processus de compr\u00e9hension. C'est pourquoi je n'utilise pas de getters ni de setters, je suis pass\u00e9 \u00e0 un autre niveau !<br \/>\nD'o\u00f9 obtenir un mod\u00e8le de co\u00fbt ? Eh bien, on peut lire quelque chose, bien s\u00fbr... Mais je pense que le meilleur moyen est d'agir. Faire un petit compilateur sera la meilleure fa\u00e7on de comprendre le mod\u00e8le de co\u00fbt et de l'int\u00e9grer dans sa propre t\u00eate. Un petit compilateur qui pourrait \u00eatre utilis\u00e9 pour programmer un micro-ondes \u2014 c'est un d\u00e9fi pour un d\u00e9butant. Je veux dire, si tu as d\u00e9j\u00e0 des comp\u00e9tences en programmation, cela devrait suffire. Toutes ces choses comme analyser une cha\u00eene qui sera une sorte d'expression alg\u00e9brique, en extraire les instructions des op\u00e9rations math\u00e9matiques dans le bon ordre, r\u00e9cup\u00e9rer les bonnes valeurs depuis les registres \u2014 tout cela se fait facilement. Et pendant que tu fais cela, cela s'imprimera dans ton cerveau. Je pense que tout le monde sait ce qu'est un compilateur. Et \u00e7a, \u00e7a donnera une compr\u00e9hension du mod\u00e8le de co\u00fbt.<\/p>\n<p><\/p>\n<h1 id=\"prakticheskie-primery-uluchsheniya-proizvoditelnosti\">Exemples pratiques d'am\u00e9lioration de la performance<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Sur quoi d'autre faut-il faire attention quand on travaille sur la performance ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Structures de donn\u00e9es. D'ailleurs, \u00e7a fait longtemps que je n'ai pas anim\u00e9 ces cours... <noindex>Rocket School<\/noindex>. C'\u00e9tait amusant, mais cela n\u00e9cessitait tant d'efforts, et j'ai aussi une vie ! Bon. Donc, lors d'un des grands et int\u00e9ressants cours, \"O\u00f9 va votre performance\", j'ai donn\u00e9 aux \u00e9tudiants un exemple : deux milliards et demi de donn\u00e9es fintech lues depuis un fichier CSV, et ensuite il fallait compter le nombre de produits vendus. Des donn\u00e9es de march\u00e9 classiques. Des paquets UDP, convertis en format texte, depuis les ann\u00e9es 70. Chicago Mercantile Exchange \u2013 toutes sortes de choses comme le p\u00e9trole, le ma\u00efs, les f\u00e8ves de soja, etc. Il fallait compter ces produits, le nombre de transactions, le volume moyen des \u00e9changes de fonds et de produits, etc. C'est des math\u00e9matiques de trading assez simples : trouver le code produit (c'est 1-2 symboles dans une table de hachage), obtenir la somme, l'ajouter \u00e0 l'un des ensembles de transactions, ajouter le volume, ajouter le co\u00fbt, et quelques autres \u00e9l\u00e9ments. Tr\u00e8s math\u00e9matique. La r\u00e9alisation simpliste \u00e9tait tr\u00e8s directe : tout se trouve dans le fichier, je lis le fichier et j'avance \u00e0 travers lui, en s\u00e9parant les enregistrements individuels en cha\u00eenes Java, en cherchant les choses dont j'ai besoin et en additionnant selon la math\u00e9matique d\u00e9crite ci-dessus. Et cela fonctionne avec une certaine lenteur. <\/p>\n<p><\/p>\n<p>Avec cette approche, il est \u00e9vident ce qui se passe, et les calculs parall\u00e8les ne seront pas utiles, n'est-ce pas ? Il s'av\u00e8re qu'un gain de performance multipli\u00e9 par cinq peut \u00eatre obtenu simplement en choisissant les bonnes structures de donn\u00e9es. Cela surprend m\u00eame les programmeurs exp\u00e9riment\u00e9s ! Dans mon cas particulier, le focus \u00e9tait de ne pas faire d'allocation de m\u00e9moire dans une boucle chaude. Bon, ce n'est pas toute la v\u00e9rit\u00e9, mais dans l'ensemble, il ne faut pas allouer \u00ab une fois tous les X \u00bb, quand X est suffisamment grand. Quand X fait deux giga-octets et demi, il ne faut rien allouer \u00ab une fois par lettre \u00bb, ou \u00ab une fois par ligne \u00bb, ou \u00ab une fois par champ \u00bb, rien de ce genre. C'est pr\u00e9cis\u00e9ment l\u00e0 que le temps est perdu. Comment cela fonctionne-t-il au juste ? Imaginez que j'appelle <code>String.split()<\/code> ou <code>BufferedReader.readLine()<\/code>. <code>Readline<\/code> fait une cha\u00eene \u00e0 partir d'un ensemble de bytes re\u00e7us sur le r\u00e9seau, une fois pour chaque ligne, pour chacune des centaines de millions de lignes. Je prends cette cha\u00eene, je l'analyse et je la jette. Pourquoi je la jette ? Eh bien, je l'ai d\u00e9j\u00e0 trait\u00e9e, c'est tout. Donc, pour chaque byte lu de ces 2.7G, deux caract\u00e8res vont \u00eatre \u00e9crits dans la cha\u00eene, soit d\u00e9j\u00e0 5.4G, et ils ne me servent \u00e0 rien par la suite, donc ils sont jet\u00e9s. Si l'on regarde la bande passante de la m\u00e9moire, nous chargeons 2.7G qui passent \u00e0 travers la m\u00e9moire et la bus m\u00e9moire dans le processeur, et ensuite deux fois plus sont envoy\u00e9s dans la cha\u00eene, r\u00e9sidant en m\u00e9moire, et tout cela est r\u00e9\u00e9crit pour chaque nouvelle cha\u00eene. Mais je dois bien la lire, le mat\u00e9riel la lit, m\u00eame si ensuite tout sera r\u00e9\u00e9crit. Et je dois l'\u00e9crire parce que j'ai cr\u00e9\u00e9 une cha\u00eene et les caches d\u00e9bordent \u2013 le cache ne peut pas contenir 2.7G. En somme, pour chaque byte lu, je lis deux bytes suppl\u00e9mentaires et j'\u00e9cris deux bytes suppl\u00e9mentaires, r\u00e9sultant en un ratio de 4:1 \u2013 ainsi, nous gaspillons inutilement la bande passante de la m\u00e9moire. Et puis il s'av\u00e8re que si je fais <code>String.split()<\/code> \u2013 je ne le fais pas pour la derni\u00e8re fois, \u00e0 l'int\u00e9rieur il peut y avoir encore 6-7 champs. Ainsi, le code classique de lecture de CSV suivi d'une analyse de cha\u00eenes entra\u00eene une perte de bande passante m\u00e9moire d'environ 14:1 par rapport \u00e0 ce que vous aimeriez vraiment avoir. Si on \u00e9limine ces allocations, on peut obtenir un gain de vitesse multipli\u00e9 par cinq. <\/p>\n<p><\/p>\n<p>Ce n'est pas vraiment tr\u00e8s compliqu\u00e9. Si vous regardez le code sous le bon angle, tout cela devient assez simple, d\u00e8s que vous avez compris le c\u0153ur du probl\u00e8me. Il ne faut surtout pas arr\u00eater d'allouer de la m\u00e9moire : le probl\u00e8me est juste que vous allouez quelque chose et cela meurt imm\u00e9diatement, et en chemin, cela consomme une ressource pr\u00e9cieuse, qui dans ce cas est la bande passante m\u00e9moire. Tout cela entra\u00eene une baisse de performance. Sur x86, il est g\u00e9n\u00e9ralement n\u00e9cessaire de br\u00fbler activement des cycles processeur, tandis qu'ici, vous avez d\u00e9j\u00e0 \u00e9puis\u00e9 toute la m\u00e9moire bien plus t\u00f4t. La solution consiste \u00e0 r\u00e9duire le nombre d'allocations.\u00a0<br \/>\nUne autre partie du probl\u00e8me est que, si vous lancez un profileur quand la bande passante m\u00e9moire est \u00e9puis\u00e9e, au moment o\u00f9 cela se produit, vous attendez g\u00e9n\u00e9ralement un retour du cache, parce qu'il est plein de d\u00e9chets que vous venez de g\u00e9n\u00e9rer avec toutes ces allocations. C'est pourquoi chaque op\u00e9ration de chargement ou de stockage devient lente, car elles entra\u00eenent des \u00e9checs de cache - tout le cache devient lent, attendant que les d\u00e9chets soient \u00e9limin\u00e9s. Ainsi, le profileur ne montrera qu'un bruit al\u00e9atoire ti\u00e8de, \u00e9tal\u00e9 sur tout le cycle - il n'y aura pas d'instruction chaude ou d'endroit distinct dans le code. Juste du bruit. Et si vous regardez les cycles de GC, ils seront tous dans la Young Generation et extr\u00eamement rapides - en microsecondes ou millisecondes au maximum. En effet, toute cette m\u00e9moire meurt instantan\u00e9ment. Vous allouez des milliards de gigaoctets, et il les coupe, et les coupe encore, et encore. Tout cela se produit tr\u00e8s rapidement. Il en r\u00e9sulte des cycles de GC peu co\u00fbteux, un bruit ti\u00e8de tout au long du cycle, mais nous voulons obtenir un acc\u00e9l\u00e9rateur 5 fois plus rapide. \u00c0 ce moment-l\u00e0, il devrait se produire une illumination dans votre esprit et vous vous direz : \u00ab Pourquoi cela ?! \u00bb. Le d\u00e9bordement de la bande passante m\u00e9moire ne s'affiche pas dans le d\u00e9bogueur classique, il faut lancer un d\u00e9bogueur de compteurs de performance mat\u00e9riels et le voir par vous-m\u00eame, directement. Sinon, on peut le soup\u00e7onner indirectement \u00e0 partir de ces trois sympt\u00f4mes. Le troisi\u00e8me sympt\u00f4me est lorsque vous regardez ce que vous allouez, demandez au profileur, et il r\u00e9pond : \u00ab Vous avez fait un milliard d'allocations, mais le GC a fonctionn\u00e9 gratuitement \u00bb. D\u00e8s que cela se produit, vous comprenez que vous avez g\u00e9n\u00e9r\u00e9 trop d'objets et \u00e9puis\u00e9 toute la bande passante m\u00e9moire. Il existe une fa\u00e7on de comprendre cela, mais elle n'est pas \u00e9vidente.\u00a0<\/p>\n<p><\/p>\n<p>Le probl\u00e8me r\u00e9side dans la structure des donn\u00e9es : une structure brute derri\u00e8re tout cela, elle est trop grande, c'est 2,7 Go sur le disque, donc faire une copie de cette chose est tr\u00e8s ind\u00e9sirable \u2013 on souhaiterait la charger directement depuis le tampon de bytes r\u00e9seau dans les registres, afin de ne pas lire et \u00e9crire en aller-retour cinq fois. Malheureusement, Java ne fournit pas par d\u00e9faut une telle biblioth\u00e8que dans le JDK. Mais c'est en r\u00e9alit\u00e9 trivial, n'est-ce pas ? En gros, cela repr\u00e9sente 5 \u00e0 10 lignes de code qui serviront \u00e0 impl\u00e9menter votre propre chargeur de lignes tamponn\u00e9es, qui r\u00e9plique le comportement de la classe string, tout en \u00e9tant une couche autour du tampon de bytes sous-jacent. Il s'av\u00e8re donc que vous travaillez presque comme si vous utilisiez des cha\u00eenes, mais en r\u00e9alit\u00e9, ce sont des pointeurs qui se d\u00e9placent dans le tampon, donc des bytes bruts ne sont copi\u00e9s nulle part, et ainsi les m\u00eames tampons sont r\u00e9utilis\u00e9s encore et encore, tandis que le syst\u00e8me d'exploitation est heureux de g\u00e9rer les \u00e9l\u00e9ments pour lesquels il est con\u00e7u, comme le double buffering cach\u00e9 de ces tampons de bytes, et vous ne broyez plus un flux infini de donn\u00e9es inutiles. Au fait, vous comprenez que, lors du travail avec le GC, il est garanti que chaque allocation de m\u00e9moire ne sera pas visible par le processeur apr\u00e8s le dernier cycle de GC ? Donc, tout cela ne peut pas se trouver dans le cache, et il en r\u00e9sulte un \u00e9chec garanti \u00e0 100 %. En utilisant un pointeur, sur x86, lire un registre en m\u00e9moire prend 1 \u00e0 2 cycles, et d\u00e8s que cela se produit, vous payez, payez, payez, parce que toute la m\u00e9moire est sur <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Cache_inclusion_policy\">NINE caches<\/a><\/noindex> \u2013 et c'est cela le co\u00fbt de l'allocation m\u00e9moire. Le v\u00e9ritable co\u00fbt.<\/p>\n<p><\/p>\n<p>En d'autres termes, les structures de donn\u00e9es sont ce qui est le plus difficile \u00e0 changer. Une fois que vous r\u00e9alisez que vous avez choisi la mauvaise structure de donn\u00e9es, qui nuira \u00e0 la performance, il faut g\u00e9n\u00e9ralement effectuer un travail consid\u00e9rable pour corriger cela. Mais si ce n'est pas fait, la situation ne fera qu'empirer. Avant tout, il est crucial de r\u00e9fl\u00e9chir aux structures de donn\u00e9es. Le co\u00fbt principal ici est associ\u00e9 aux structures de donn\u00e9es encombrantes, que l'on commence \u00e0 utiliser dans le style \"j'ai copi\u00e9 la structure de donn\u00e9es X dans la structure de donn\u00e9es Y parce que Y me semble plus attrayante\". Mais l'op\u00e9ration de copie (qui semble peu co\u00fbteuse) consomme en r\u00e9alit\u00e9 de la bande passante en m\u00e9moire et c'est ici que le temps d'ex\u00e9cution est perdu. Si j'ai une gigantesque cha\u00eene JSON et que je veux la transformer en un arbre DOM structur\u00e9 \u00e0 partir de POJO ou quelque chose comme \u00e7a, l'op\u00e9ration de parsing de cette cha\u00eene et de construction de POJO, puis l'acc\u00e8s ult\u00e9rieur \u00e0 POJO entra\u00eenera un co\u00fbt suppl\u00e9mentaire \u2013 ce n'est pas bon march\u00e9. \u00c0 moins que vous n'utilisiez les POJO beaucoup plus souvent que la cha\u00eene. En gros, vous pourriez essayer de d\u00e9coder la cha\u00eene et d'en extraire seulement ce dont vous avez besoin, sans la transformer en POJO. Si tout cela se d\u00e9roule l\u00e0 o\u00f9 une performance maximale est requise, oubliez les POJO \u2013 il faut fouiller directement dans la cha\u00eene.<\/p>\n<p><\/p>\n<h1 id=\"zachem-sozdavat-svoy-yazyk-programmirovaniya\">Pourquoi cr\u00e9er son propre langage de programmation<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Vous avez dit que pour comprendre le mod\u00e8le de co\u00fbt, il faut \u00e9crire votre propre petit langage...<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Ce n'est pas un langage, mais un compilateur. Un langage et un compilateur sont des choses diff\u00e9rentes. La principale distinction se trouve dans votre esprit.\u00a0<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: \u00c0 propos, d'apr\u00e8s ce que je sais, vous exp\u00e9rimentez la cr\u00e9ation de langages propres. Pourquoi ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Parce que je peux ! Je suis \u00e0 moiti\u00e9 \u00e0 la retraite, donc c'est mon hobby. J'ai pass\u00e9 ma vie \u00e0 r\u00e9aliser les langages de quelqu'un d'autre. J'ai \u00e9galement beaucoup travaill\u00e9 sur le style de codage. En plus, je vois des probl\u00e8mes dans d'autres langages. Je vois qu'il existe des mani\u00e8res meilleures de faire des choses habituelles. Et je les utiliserais. Je suis juste fatigu\u00e9 de voir des probl\u00e8mes en moi, dans Java, dans Python, dans tout autre langage. En ce moment, j'\u00e9cris en React Native, JavaScript et Elm comme hobby, qui n'est pas li\u00e9 \u00e0 la retraite, mais \u00e0 un travail actif. Je programme aussi en Python et probablement, je vais continuer \u00e0 travailler sur l'apprentissage automatique pour des backends Java. Il existe de nombreux langages populaires, chacun ayant des caract\u00e9ristiques int\u00e9ressantes. Chacun est bon \u00e0 sa mani\u00e8re et on peut essayer de r\u00e9unir toutes ces particularit\u00e9s. Donc, je m'engage dans l'\u00e9tude de choses qui m'int\u00e9ressent, le comportement des langages, en essayant de trouver une s\u00e9mantique raisonnable. Et pour l'instant, \u00e7a fonctionne bien pour moi ! Actuellement, je lutte avec la s\u00e9mantique de la m\u00e9moire, car je voudrais qu'elle soit comme en C et Java, et obtenir un mod\u00e8le de m\u00e9moire fort et une s\u00e9mantique de m\u00e9moire pour les chargements et les stockages. En m\u00eame temps, j'aimerais avoir une inf\u00e9rence de type automatique comme en Haskell. Voil\u00e0, j'essaie de m\u00e9langer une inf\u00e9rence de type de style Haskell avec une m\u00e9moire fonctionnant comme en C et Java. Je m'y consacre depuis 2-3 mois, par exemple.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Si vous construisez un langage qui prend le meilleur des aspects d'autres langages, avez-vous pens\u00e9 que quelqu'un pourrait faire l'inverse : prendre vos id\u00e9es et les utiliser ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: C'est ainsi que de nouveaux langages apparaissent ! Pourquoi Java ressemble-t-il \u00e0 C ? Parce que C avait une bonne syntaxe que tout le monde comprenait et que Java s'est inspir\u00e9 de cette syntaxe, en y ajoutant la s\u00e9curit\u00e9 des types, les v\u00e9rifications de limites de tableaux, le GC, et am\u00e9liorant certaines choses de C. Ils ont ajout\u00e9 leurs propres \u00e9l\u00e9ments. Mais ils se sont beaucoup inspir\u00e9s, n'est-ce pas ? Tout le monde se tient sur les \u00e9paules de g\u00e9ants qui \u00e9taient l\u00e0 avant vous - c'est ainsi que progresse la science.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: D'apr\u00e8s ce que je comprends, votre langage sera s\u00fbr en ce qui concerne l'utilisation de la m\u00e9moire. Envisagez-vous de mettre en \u0153uvre quelque chose comme le borrow checker de Rust ? Vous l'avez regard\u00e9, qu'en pensez-vous ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Eh bien, j'\u00e9cris en C depuis une \u00e9ternit\u00e9, avec tous ces malloc et free, et je g\u00e8re manuellement le cycle de vie. Vous savez, 90-95 % du cycle de vie g\u00e9r\u00e9 manuellement a la m\u00eame structure. Et c'est tr\u00e8s, tr\u00e8s p\u00e9nible de faire cela \u00e0 la main. J'aimerais que le compilateur indique simplement ce qui se passe et ce que j'ai accompli gr\u00e2ce \u00e0 mes actions. Pour certaines choses, le v\u00e9rificateur d'emprunt le fait par d\u00e9faut. De plus, il devrait automatiquement fournir des informations, tout comprendre et ne m\u00eame pas me surcharger en exposant cette compr\u00e9hension. Il doit faire au moins une analyse d'\u00e9vasion locale, et uniquement si cela \u00e9choue, il faut alors ajouter des annotations de type qui d\u00e9crivent le cycle de vie \u2013 et un tel sch\u00e9ma est bien plus complexe que le v\u00e9rificateur d'emprunt, ou tout autre v\u00e9rificateur de m\u00e9moire existant. Le choix entre \u00ab tout va bien \u00bb et \u00ab je n'ai rien compris \u00bb \u2014 non, il devrait y avoir quelque chose de mieux.\u00a0<br \/>\nEn tant que personne ayant beaucoup programm\u00e9 en C, je consid\u00e8re que le support de la gestion automatique du cycle de vie est d'une importance cruciale. De plus, je suis lass\u00e9 de la mani\u00e8re dont Java utilise la m\u00e9moire, ma principale plainte \u00e9tant li\u00e9e au GC. Lors de l'allocation de m\u00e9moire en Java, la m\u00e9moire qui \u00e9tait locale lors du dernier cycle de GC n'est pas r\u00e9cup\u00e9r\u00e9e. Dans les langages avec une gestion de la m\u00e9moire plus pr\u00e9cise, cela ne se passe pas ainsi. Si vous appelez malloc, vous obtenez imm\u00e9diatement de la m\u00e9moire qui a g\u00e9n\u00e9ralement \u00e9t\u00e9 utilis\u00e9e juste avant. En g\u00e9n\u00e9ral, vous faites des choses temporaires avec la m\u00e9moire et la rendez rapidement. Cela permet de la renvoyer imm\u00e9diatement dans le pool de malloc, et le cycle de malloc suivant la r\u00e9cup\u00e8re ensuite. Par cons\u00e9quent, l'utilisation r\u00e9elle de la m\u00e9moire est r\u00e9duite \u00e0 l'ensemble des objets vivants \u00e0 un moment donn\u00e9, plus les fuites. Et tant que vous n'avez pas de fuites de m\u00e9moire de mani\u00e8re flagrante, la majeure partie de la m\u00e9moire est retenue dans les caches et le processeur, ce qui fonctionne rapidement. Mais cela n\u00e9cessite beaucoup de gestion manuelle de la m\u00e9moire \u00e0 l'aide de malloc et free, appel\u00e9s dans le bon ordre et au bon endroit. Rust peut g\u00e9rer cela correctement et dans de nombreux cas, offrir m\u00eame de meilleures performances, car la consommation de m\u00e9moire se r\u00e9duit uniquement aux calculs en cours \u2013 contrairement \u00e0 l'attente du prochain cycle de GC pour lib\u00e9rer de la m\u00e9moire. En fin de compte, nous avons un moyen tr\u00e8s int\u00e9ressant d'am\u00e9liorer les performances. Et c'est assez puissant \u2013 en ce sens, j'ai travaill\u00e9 sur ce genre de chose dans le traitement des donn\u00e9es pour le fintech, et cela permettait un gain de performance d'environ cinq fois. C'est un gain consid\u00e9rable, surtout dans un monde o\u00f9 les processeurs ne deviennent pas plus rapides, alors que nous continuons \u00e0 attendre des am\u00e9liorations.<\/p>\n<p><\/p>\n<h1 id=\"karera-performans-inzhenera\">Carri\u00e8re d'ing\u00e9nieur en performance<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Je voudrais aussi poser quelques questions sur la carri\u00e8re en g\u00e9n\u00e9ral. Vous \u00eates devenu c\u00e9l\u00e8bre gr\u00e2ce \u00e0 votre travail sur le JIT dans HotSpot, puis vous \u00eates pass\u00e9 chez Azul \u2013 qui est \u00e9galement une entreprise JVM. Mais vous vous \u00eates concentr\u00e9 davantage sur le mat\u00e9riel que sur le logiciel. Ensuite, vous avez soudainement pivot\u00e9 vers le Big Data et l'apprentissage automatique, puis vers la d\u00e9tection de fraude. Comment cela s'est-il produit ? Ce sont des domaines de d\u00e9veloppement tr\u00e8s diff\u00e9rents.<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Je programme depuis assez longtemps et j'ai eu l'occasion de participer \u00e0 des projets tr\u00e8s vari\u00e9s. Et quand les gens disent : \u00ab oh, tu es celui qui a fait JIT pour Java ! \u00bb, c'est toujours amusant. Avant cela, je travaillais sur un clone de PostScript \u2013 ce langage qu'Apple utilisait autrefois pour ses imprimantes laser. Et avant cela, j'avais r\u00e9alis\u00e9 le langage Forth. Je pense que le th\u00e8me commun pour moi est le d\u00e9veloppement d'outils. J'ai toujours cr\u00e9\u00e9 des outils permettant \u00e0 d'autres personnes d'\u00e9crire leurs super programmes. Mais j'ai \u00e9galement travaill\u00e9 sur le d\u00e9veloppement de syst\u00e8mes d'exploitation, de pilotes, de d\u00e9bogueurs au niveau du noyau, de langages pour d\u00e9velopper des syst\u00e8mes d'exploitation, qui commen\u00e7aient de fa\u00e7on triviale mais devenaient de plus en plus complexes avec le temps. Mais le sujet principal, tout de m\u00eame, reste le d\u00e9veloppement d'outils. Une grande partie de ma vie s'est \u00e9coul\u00e9e entre Azul et Sun, et cela concernait Java. Mais lorsque je me suis plong\u00e9 dans le Big Data et le Machine Learning, j'ai de nouveau mis mon chapeau de gala et dit : \u00ab Oh, maintenant nous avons un probl\u00e8me non trivial, et il se passe vraiment plein de choses int\u00e9ressantes avec des gens qui font quelque chose. \u00bb C'est une excellente voie de d\u00e9veloppement \u00e0 explorer. <\/p>\n<p><\/p>\n<p>Oui, j'adore vraiment le calcul distribu\u00e9. Mon premier emploi a \u00e9t\u00e9 pendant mes \u00e9tudes en C, sur un projet publicitaire. C'\u00e9tait du calcul distribu\u00e9 sur des puces Zilog Z80, qui collectaient des donn\u00e9es pour la reconnaissance optique de caract\u00e8res analogique r\u00e9alis\u00e9e par un v\u00e9ritable analyseur analogique. C'\u00e9tait un sujet fascinant et compl\u00e8tement atypique. Mais il y avait des probl\u00e8mes, certaines parties n'\u00e9taient pas reconnues correctement, donc il fallait extraire l'image et la montrer \u00e0 une personne qui pouvait d\u00e9j\u00e0 lire et indiquer ce qu'il y avait. Ainsi, il y avait des t\u00e2ches de donn\u00e9es et ces t\u00e2ches avaient leur propre langage. Il y avait un backend qui traitait tout cela - des Z80 fonctionnant en parall\u00e8le avec des terminaux vt100 - un par personne, et il y avait un mod\u00e8le de programmation parall\u00e8le sur Z80. Un morceau de m\u00e9moire partag\u00e9, que tous les Z80 partageaient au sein d'une configuration en \u00e9toile ; la carte de support \u00e9tait \u00e9galement partag\u00e9e, et la moiti\u00e9 de la RAM \u00e9tait partag\u00e9e au sein du r\u00e9seau, tandis que l'autre moiti\u00e9 \u00e9tait priv\u00e9e ou utilis\u00e9e ailleurs. Un syst\u00e8me parall\u00e8le distribu\u00e9 complexe avec une m\u00e9moire\u2026 semi-partag\u00e9e. Quand cela a-t-il eu lieu\u2026 Je ne me souviens d\u00e9j\u00e0 plus, quelque part au milieu des ann\u00e9es 80. C'\u00e9tait il y a longtemps.\u00a0<br \/>\nOui, consid\u00e9rons que 30 ans, c'est assez longtemps. Les t\u00e2ches li\u00e9es au calcul distribu\u00e9 existent depuis assez longtemps, les gens se battent depuis longtemps avec <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/Beowulf_(%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80)\">Beowulf<\/a><\/noindex>-clusters. Ces clusters ressemblent \u00e0... Par exemple : il y a l'Ethernet et ton x86 rapide est connect\u00e9 \u00e0 cet Ethernet, et maintenant tu veux obtenir une fake shared memory, parce que personne ne pouvait \u00e0 l'\u00e9poque s'occuper de la programmation des calculs distribu\u00e9s, c'\u00e9tait trop compliqu\u00e9 et donc il y avait une fake shared memory avec protection des pages m\u00e9moire sur x86, et si tu \u00e9crivais dans cette page, nous disions aux autres processeurs que s'ils acc\u00e9daient \u00e0 la m\u00eame shared memory, elle devait \u00eatre charg\u00e9e depuis toi, et c'est ainsi qu'un protocole de support de coh\u00e9rence de cache et de logiciel pour cela est apparu. Concept int\u00e9ressant. Le vrai probl\u00e8me, bien s\u00fbr, \u00e9tait ailleurs. Tout cela fonctionnait, mais tu rencontrais rapidement des probl\u00e8mes de performance, car personne ne comprenait le mod\u00e8le de performance \u00e0 un niveau suffisamment bon \u2013 quels \u00e9taient les motifs d'acc\u00e8s \u00e0 la m\u00e9moire, comment faire en sorte que les n\u0153uds ne se pingent pas ind\u00e9finiment, et ainsi de suite. <\/p>\n<p><\/p>\n<p>Dans H2O, j'ai con\u00e7u une approche o\u00f9 les d\u00e9veloppeurs sont responsables de d\u00e9terminer o\u00f9 se cache le parall\u00e9lisme et o\u00f9 il n'est pas. J'ai \u00e9labor\u00e9 un mod\u00e8le de codage qui facilite l'\u00e9criture de code haute performance. En revanche, \u00e9crire du code qui fonctionne lentement est complexe et a une apparence peu attrayante. Il faut un v\u00e9ritable effort pour produire un code lent, notamment en recourant \u00e0 des m\u00e9thodes non standard. Un code ralentissant se remarque imm\u00e9diatement. Par cons\u00e9quent, le code est g\u00e9n\u00e9ralement \u00e9crit pour \u00eatre rapide, mais il faut alors se pencher sur la gestion de la m\u00e9moire partag\u00e9e. Tout cela est li\u00e9 \u00e0 de grands tableaux et le comportement est similaire \u00e0 celui de grands tableaux non volatils dans le parall\u00e9lisme en Java. Imaginez que deux threads \u00e9crivent dans un tableau parall\u00e8le, l'un d'eux l'emporte, et l'autre perd, sans que vous sachiez lequel est lequel. S'ils ne sont pas volatils, l'ordre peut \u00eatre n'importe quel \u2013 et cela fonctionne r\u00e9ellement tr\u00e8s bien. Les gens se soucient vraiment de l'ordre des op\u00e9rations, ils positionnent correctement les mots-cl\u00e9s volatile et anticipent bien les probl\u00e8mes de performance li\u00e9s \u00e0 la m\u00e9moire. Sinon, ils \u00e9criraient simplement du code sous la forme de boucles de 1 \u00e0 N, o\u00f9 N repr\u00e9sente des trillions, en esp\u00e9rant que tous les cas complexes deviennent automatiquement parall\u00e8les \u2013 mais cela ne fonctionne pas. Cependant, H2O ce n'est ni Java ni Scala, on peut consid\u00e9rer cela comme \u00ab Java moins moins \u00bb, si on le veut. C'est un style de programmation tr\u00e8s compr\u00e9hensible, ressemblant \u00e0 l'\u00e9criture de code simple en C ou Java avec des boucles et des tableaux. En m\u00eame temps, la m\u00e9moire peut \u00eatre manipul\u00e9e par t\u00e9raoctets. J'utilise toujours H2O. De temps en temps, je l'emploie dans diff\u00e9rents projets \u2013 et c'est jusqu'\u00e0 pr\u00e9sent la solution la plus rapide, devan\u00e7ant la concurrence de plusieurs dizaines de fois. Si vous traitez des Big Data avec des donn\u00e9es en colonnes, il est tr\u00e8s difficile de surpasser H2O.<\/p>\n<p><\/p>\n<h1 id=\"tehnicheskie-chellenzhi\">D\u00e9fis techniques<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Quel a \u00e9t\u00e9 le plus grand d\u00e9fi de votre carri\u00e8re ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Discutons-nous de la partie technique ou non technique de la question ? Je dirais que les plus grands d\u00e9fis sont non techniques.\u00a0<br \/>\nEn ce qui concerne les d\u00e9fis techniques. Je les ai simplement surmont\u00e9s. Je ne sais m\u00eame pas quel a \u00e9t\u00e9 le plus grand, mais il y en a eu plusieurs plut\u00f4t int\u00e9ressants qui ont demand\u00e9 beaucoup de temps et de lutte mentale. Lorsque j'ai rejoint Sun, j'\u00e9tais convaincu que je ferais un compilateur rapide, tandis qu'une multitude de seniors disait que je n'y arriverais jamais. Mais j'ai emprunt\u00e9 ce chemin, j'ai \u00e9crit un compilateur jusqu'\u00e0 l'allocateur de registres, et il \u00e9tait assez rapide. Il \u00e9tait aussi rapide que le C1 moderne, mais \u00e0 l'\u00e9poque, l'allocateur \u00e9tait beaucoup plus lent, et en y repensant, c'\u00e9tait un probl\u00e8me de grande structure de donn\u00e9es. J'en avais besoin pour \u00e9crire un allocateur de registres graphique et je ne comprenais pas le dilemme entre l'expressivit\u00e9 du code et la vitesse, qui \u00e9tait tr\u00e8s important \u00e0 cette \u00e9poque. Il s'est av\u00e9r\u00e9 que la structure de donn\u00e9es d\u00e9passait g\u00e9n\u00e9ralement la taille du cache sur les x86 de cette \u00e9poque, donc, si je supposais au d\u00e9part que l'allocateur de registres travaillerait 5-10 % du temps de compilation juste-\u00e0-temps (JIT), en r\u00e9alit\u00e9, cela se traduisait par 50 %. <\/p>\n<p><\/p>\n<p>Avec le temps, le compilateur devenait de plus en plus pr\u00e9cis et performant, il cessait de g\u00e9n\u00e9rer du code horrible dans un plus grand nombre de cas, et la performance commen\u00e7ait de plus en plus \u00e0 ressembler \u00e0 celle d'un compilateur C. Sauf si, bien s\u00fbr, vous \u00e9criviez une sorte de code tellement mauvais que m\u00eame C ne l'acc\u00e9l\u00e9rerait pas. Si vous \u00e9criviez du code comme en C, vous aviez \u00e9galement des performances similaires \u00e0 C dans la plupart des cas. Et de plus en plus souvent, le code obtenait une performance asymptotiquement \u00e9quivalente \u00e0 celle du C, et l'allocateur de registres commen\u00e7ait \u00e0 ressembler \u00e0 quelque chose de complet\u2026 peu importe si votre code s'ex\u00e9cutait rapidement ou lentement. Je continuais \u00e0 travailler sur l'allocateur pour qu'il fasse de meilleures allocations. Il devenait de plus en plus lent, mais offrait des performances toujours meilleures dans les cas o\u00f9 personne n'y arrivait. Je pouvais plonger dans l'allocateur de registres, y enfouir un mois de travail, et soudain tout le code commen\u00e7ait \u00e0 s'ex\u00e9cuter 5 % plus rapidement. Cela se produisait encore et encore et l'allocateur de registres \u00e9tait devenu une sorte d'\u0153uvre d'art \u2013 tout le monde l'aimait ou le d\u00e9testait, et les gens du milieu acad\u00e9mique posaient des questions sur \u00ab pourquoi tout \u00e9tait fait de cette mani\u00e8re \u00bb, pourquoi pas. <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Register_allocation#Linear_Scan\">balayage lin\u00e9aire<\/a><\/noindex>, et quelle est la diff\u00e9rence. La r\u00e9ponse est la m\u00eame : un allocate bas\u00e9 sur le coloriage du graphe plus un code tampon tr\u00e8s soign\u00e9 \u00e9quivaut \u00e0 un instrument de victoire, la meilleure combinaison que personne ne peut battre. Et c'est une chose assez subtile. Tout le reste que le compilateur fait \u2013 ce sont des choses plut\u00f4t bien connues, m\u00eame si elles ont \u00e9t\u00e9 port\u00e9es \u00e0 un niveau artistique. J'ai toujours fait des choses qui devaient transformer le compilateur en \u0153uvre d'art. Mais rien de tout cela n'\u00e9tait extraordinaire \u2013 \u00e0 l'exception de l'allocateur de registres. Le point est qu'il faut le faire avec pr\u00e9caution <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Register_allocation\">couper<\/a><\/noindex> sous charge et, si cela se produit (je peux expliquer plus en d\u00e9tail si cela vous int\u00e9resse), cela signifie qu'il est possible de proc\u00e9der \u00e0 une int\u00e9gration plus agressive, sans risque de d\u00e9passer la rupture de la courbe de performance. \u00c0 l'\u00e9poque, il y avait plein de compilateurs complets, orn\u00e9s de gadgets et de sifflets, qui avaient des allocateurs de registres, mais personne n'a r\u00e9ussi \u00e0 faire mieux depuis. <\/p>\n<p><\/p>\n<p>Le probl\u00e8me est que, si vous ajoutez des m\u00e9thodes pouvant \u00eatre int\u00e9gr\u00e9es, en augmentant sans cesse le champ d'int\u00e9gration, l'ensemble des valeurs utilis\u00e9es d\u00e9passe imm\u00e9diatement le nombre de registres, et vous devez faire du spilling. Le niveau critique survient g\u00e9n\u00e9ralement lorsque l'allocateur abandonne, et un bon candidat pour le spilling vaut un autre, vous faites du spilling sur des choses totalement \u00e9tranges. La valeur de l'inlining r\u00e9side dans le fait que vous perdez une partie de l'overhead, l'overhead d'appel et de sauvegarde, vous pouvez voir les valeurs \u00e0 l'int\u00e9rieur et vous pouvez continuer \u00e0 les optimiser. Le co\u00fbt de l'inlining r\u00e9side dans le fait qu'un grand nombre de valeurs vivantes se forment, et si votre allocateur de registres fait plus de spilling que n\u00e9cessaire, vous perdez imm\u00e9diatement. Ainsi, la plupart des allocateurs ont ce probl\u00e8me : quand l'inlining d\u00e9passe un certain seuil, tout commence \u00e0 faire du spilling, et les performances peuvent \u00eatre r\u00e9duites \u00e0 n\u00e9ant. Ceux qui r\u00e9alisent des compilateurs ajoutent certaines heuristiques : par exemple, pour arr\u00eater l'inlining \u00e0 partir d'une taille suffisante, car les allocations peuvent tout g\u00e2cher. Cela cr\u00e9e une rupture dans le graphique de performance : vous ins\u00e9rez, ins\u00e9rez, la performance augmente lentement \u2013 puis boum ! \u2013 elle chute comme un marteau, parce que vous avez int\u00e9gr\u00e9 trop de choses. Ainsi, tout fonctionnait jusqu'\u00e0 l'arriv\u00e9e de Java. Java exige beaucoup plus d'inlining, donc j'ai d\u00fb rendre mon allocateur beaucoup plus agressif pour qu'il s'ajuste plut\u00f4t que de tomber, et si vous avez trop int\u00e9gr\u00e9 \u2013 il commence \u00e0 faire du spilling, mais arrive n\u00e9anmoins le moment o\u00f9 il n'y a plus de spilling. C'est une observation int\u00e9ressante et elle m'est venue de nulle part, non \u00e9vidente, mais bien rentable. J'ai adopt\u00e9 un inlining agressif et cela m'a conduit \u00e0 des endroits o\u00f9 les performances de Java et C sont c\u00f4te \u00e0 c\u00f4te. Ils sont r\u00e9ellement proches \u2013 je peux \u00e9crire du code en Java qui sera significativement plus rapide que le code en C et ainsi de suite, mais en moyenne, dans la grande image des choses, ils sont \u00e0 peu pr\u00e8s comparables. Il semble qu'une partie de ce m\u00e9rite provienne de l'allocateur de registres, qui me permet d'int\u00e9grer de mani\u00e8re maximale. Je fais simplement de l'inlining sur tout ce que je vois. La question ici est de savoir si l'allocateur fonctionne bien, si le code r\u00e9sultant fonctionne de mani\u00e8re raisonnable. Cela a \u00e9t\u00e9 un grand d\u00e9fi : comprendre tout cela et r\u00e9ussir \u00e0 le faire fonctionner.<\/p>\n<p><\/p>\n<h1 id=\"nemnogo-pro-allokaciyu-registrov-i-mnogoyadernost\">Un peu sur l'allocation des registres et le multithreading<\/h1>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: Les probl\u00e8mes comme l'allocation des registres semblent \u00eatre un sujet \u00e9ternel. Est-ce qu'il est possible qu'une id\u00e9e ait sembl\u00e9 prometteuse et qu'en pratique, elle ait \u00e9chou\u00e9 ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Bien s\u00fbr ! L'allocation des registres est un domaine o\u00f9, pour r\u00e9soudre un probl\u00e8me NP-complet, tu essaies de trouver des heuristiques. Et tu ne pourras jamais obtenir une solution parfaite, n'est-ce pas ? C'est juste impossible. Regardez, la compilation Ahead of Time \u2013 elle fonctionne aussi mal. On parle ici de cas moyens. De performances typiques, afin que tu puisses aller et mesurer quelque chose que tu consid\u00e8res comme une bonne performance typique \u2013 apr\u00e8s tout, tu travailles pour l'am\u00e9liorer ! L'allocation des registres est un sujet enti\u00e8rement d\u00e9di\u00e9 \u00e0 la performance. D\u00e8s que tu as un premier prototype, il fonctionne et fait ce qu'il doit, le travail sur la performance commence. Il faut apprendre \u00e0 bien mesurer. Pourquoi est-ce important ? S'il y a des donn\u00e9es claires, on peut regarder diff\u00e9rentes parties et voir : ah, cela a aid\u00e9 ici, mais l\u00e0, tout a \u00e9chou\u00e9 ! Il y a de bonnes id\u00e9es qui apparaissent, tu ajoutes une nouvelle heuristique et soudainement, tout fonctionne un peu mieux en moyenne. Ou pas. J'ai eu beaucoup de cas o\u00f9 nous avons lutt\u00e9 pour cinq pourcents de performance qui distinguaient notre d\u00e9veloppement de l'allocateur pr\u00e9c\u00e9dent. Et chaque fois, \u00e7a ressemble \u00e0 \u00e7a : on gagne quelque part, on perd ailleurs. Si tu as de bons outils d'analyse de performance, tu peux trouver les id\u00e9es perdantes et comprendre pourquoi elles \u00e9chouent. Peut-\u00eatre qu'il vaut mieux laisser les choses telles qu'elles sont, ou alors s'attaquer s\u00e9rieusement \u00e0 l'optimisation fine, ou aller r\u00e9parer autre chose. C'est tout un ensemble de choses ! J'ai fait ce super hack, mais j'ai besoin de celui-ci, et de celui-l\u00e0, et de celui-ci \u2013 et leur combinaison totale apporte quelques am\u00e9liorations. Et les solutions isol\u00e9es peuvent \u00e9chouer. C'est la nature du travail sur la performance des probl\u00e8mes NP-complets.<\/p>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: On a l'impression que des choses comme la coloration dans les allocateurs sont des t\u00e2ches d\u00e9j\u00e0 r\u00e9solues. Eh bien, elles le sont pour vous, vu ce que vous racontez, alors cela vaut-il vraiment la peine de...<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Elle n'est pas r\u00e9solue en tant que telle. C'est \u00e0 toi de la transformer en \u00ab r\u00e9solue \u00bb. Il existe des t\u00e2ches difficiles \u00e0 accomplir et il faut s'y attaquer. Une fois cela fait, il est temps de se concentrer sur la performance. Il faut aborder ce travail de mani\u00e8re appropri\u00e9e \u2013 faire des benchmarks, collecter des m\u00e9triques, expliquer les situations dans lesquelles, apr\u00e8s un retour \u00e0 une version ant\u00e9rieure, ton ancien hack a recommenc\u00e9 \u00e0 fonctionner (ou au contraire, a cess\u00e9 de fonctionner). Et ne pas reculer jusqu'\u00e0 ce que tu aies quelque chose \u00e0 montrer. Comme je l'ai d\u00e9j\u00e0 dit, si des id\u00e9es int\u00e9ressantes n'ont pas fonctionn\u00e9, il y a environ une infinit\u00e9 d'id\u00e9es dans le domaine de l'allocation de registres. On peut par exemple lire des publications scientifiques. Bien que ce domaine ait commenc\u00e9 \u00e0 avancer beaucoup plus lentement et soit devenu plus clair qu'\u00e0 ses d\u00e9buts. N\u00e9anmoins, une infinit\u00e9 de personnes travaille dans ce domaine, et toutes leurs id\u00e9es m\u00e9ritent d'\u00eatre test\u00e9es, elles attendent toutes leur tour. Et tu ne peux pas dire \u00e0 quel point elles sont bonnes si tu ne les essayes pas. \u00c0 quel point elles s'int\u00e8grent bien \u00e0 tout le reste dans ton allocateur, car l'allocateur effectue de nombreuses t\u00e2ches, et certaines id\u00e9es dans ton allocateur en particulier peuvent ne pas fonctionner, alors que dans un autre, \u00e7a pourrait tr\u00e8s bien marcher. Le principal moyen de victoire pour un allocateur est d'extraire les \u00e9l\u00e9ments lents hors du chemin principal et de forcer le fractionnement aux fronti\u00e8res des chemins lents. Donc, si tu veux ex\u00e9cuter le GC, suivre le chemin lent, se d\u00e9optimiser, lancer une exception, tout \u00e7a \u2013 tu sais que ces choses sont relativement rares. Et elles sont vraiment rares, j'ai v\u00e9rifi\u00e9. Tu fais un travail suppl\u00e9mentaire et, gr\u00e2ce \u00e0 cela, de nombreuses limitations sur ces chemins lents disparaissent, mais ce n'est pas tr\u00e8s important, car ils sont lents et peu fr\u00e9quent\u00e9s. Par exemple, un pointeur nul, \u00e7a n'arrive jamais, n'est-ce pas ? Il faut avoir plusieurs chemins pour diff\u00e9rentes choses, mais ils ne doivent pas interf\u00e9rer avec le principal.\u00a0<\/p>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: Que penses-tu de la multiprocession, quand il y a des milliers de c\u0153urs \u00e0 la fois ? C'est quelque chose d'utile ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Le succ\u00e8s des GPU montre que c'est plut\u00f4t utile !<\/p>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: Ils sont assez sp\u00e9cialis\u00e9s. Et qu'en est-il des processeurs \u00e0 usage g\u00e9n\u00e9ral ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Eh bien, c'\u00e9tait le mod\u00e8le commercial d'Azul. La r\u00e9ponse est venue \u00e0 une \u00e9poque o\u00f9 les gens aimaient beaucoup la performance pr\u00e9visible. \u00c0 l'\u00e9poque, il \u00e9tait difficile d'\u00e9crire du code parall\u00e8le. Le mod\u00e8le de codage H2O se pr\u00eate bien \u00e0 l'\u00e9volutivit\u00e9, mais ce n'est pas un mod\u00e8le \u00e0 usage g\u00e9n\u00e9ral. \u00c0 moins qu'il soit l\u00e9g\u00e8rement plus g\u00e9n\u00e9ral que l'utilisation du GPU. Parlons-nous de la complexit\u00e9 du d\u00e9veloppement de ce genre de chose ou de sa complexit\u00e9 d'utilisation ? Par exemple, une le\u00e7on int\u00e9ressante qu'Azul m'a apprise, assez subtile : les petits caches, c'est acceptable.\u00a0<\/p>\n<p><\/p>\n<h1 id=\"samyy-bolshoy-chellenzh-v-zhizni\">Le plus grand d\u00e9fi de la vie<\/h1>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: Qu'en est-il des d\u00e9fis non techniques ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Le plus grand d\u00e9fi a \u00e9t\u00e9 de ne pas \u00eatre\u2026 gentil et bon avec les gens. En cons\u00e9quence, je me retrouvais constamment dans des situations conflictuelles extr\u00eames. Des situations o\u00f9 je savais que tout allait de travers, mais je ne savais pas comment avancer dans la r\u00e9solution de ces probl\u00e8mes et je ne pouvais pas les g\u00e9rer. De nombreux probl\u00e8mes persistants, qui durent des d\u00e9cennies, sont apparus de cette mani\u00e8re. Le fait qu'il y ait des compilateurs C1 et C2 en Java en est une cons\u00e9quence directe. L'absence de compilation multi-niveaux en Java pendant une d\u00e9cennie en est \u00e9galement une cons\u00e9quence directe. Il est \u00e9vident qu'un tel syst\u00e8me \u00e9tait n\u00e9cessaire, mais il n'est pas \u00e9vident pourquoi il n'existait pas. J'ai eu des probl\u00e8mes avec un ing\u00e9nieur\u2026 ou un groupe d'ing\u00e9nieurs. Il y a longtemps, quand j'ai commenc\u00e9 \u00e0 travailler chez Sun, j'\u00e9tais\u2026 Bon, pas seulement \u00e0 cette \u00e9poque, j'ai toujours eu mon propre avis sur tout. Et je croyais fermement qu'il suffisait de dire cette v\u00e9rit\u00e9 en face. Surtout que j'avais souvent raison de mani\u00e8re choquante. Et si ce type d'approche ne te convient pas\u2026 surtout si tu es manifestement dans l'erreur et que tu dis des b\u00eatises\u2026 En gros, peu de gens pouvaient tol\u00e9rer ce mode de communication. Pourtant, certains pouvaient, comme moi par exemple. J'ai construit ma vie sur des principes m\u00e9ritocratiques. Si tu me montres quelque chose de faux, je me retournerai imm\u00e9diatement et dirai : tu racontes des b\u00eatises. Tout en m'excusant bien s\u00fbr, en reconnaissant les m\u00e9rites s'il y en a, et en faisant d'autres actions correctes. D'un autre c\u00f4t\u00e9, j'ai souvent raison de mani\u00e8re choquante une grande partie du temps. Et cela ne fonctionne pas tr\u00e8s bien dans les relations avec les gens. Je n'essaie m\u00eame pas d'\u00eatre aimable, je pose la question de mani\u00e8re directe. \u00ab Cela ne fonctionnera jamais, parce qu'une, deux et trois \u00bb. Et ils r\u00e9agissent : \u00ab Oh ! \u00bb. Il y a eu d'autres cons\u00e9quences, que j'aurais probablement int\u00e9r\u00eat \u00e0 omettre : par exemple, celles qui ont conduit \u00e0 mon divorce et \u00e0 une d\u00e9cennie de d\u00e9pression qui a suivi.<\/p>\n<p><\/p>\n<p>Le d\u00e9fi est une lutte contre les perceptions des gens sur ce que vous pouvez ou ne pouvez pas faire, sur ce qui est important et ce qui ne l'est pas. Il y a eu de nombreux d\u00e9fis concernant le style de codage. J'\u00e9cris encore beaucoup de code et \u00e0 l'\u00e9poque, j'ai m\u00eame d\u00fb ralentir, car je faisais trop de t\u00e2ches en parall\u00e8le et je les faisais mal, au lieu de me concentrer sur une seule. En r\u00e9fl\u00e9chissant, j'ai \u00e9crit la moiti\u00e9 du code de l'\u00e9quipe Java JIT, l'\u00e9quipe C2. Le prochain coder le plus rapide \u00e9crivait deux fois plus lentement, le suivant \u00e9tait encore plus lent, et c'\u00e9tait une chute exponentielle. La septi\u00e8me personne de cette cha\u00eene \u00e9tait tr\u00e8s, tr\u00e8s lente \u2013 cela arrive toujours ! J'ai touch\u00e9 \u00e0 une foule de codes. Je regardais qui \u00e9crivait quoi, sans exceptions, je scrutais leur code, je r\u00e9visais chacun d'eux, et je continuais \u00e0 \u00e9crire plus que n'importe lequel d'entre eux. Avec les gens, cette approche ne fonctionne pas tr\u00e8s bien. Certains n'aiment pas cela. Et quand ils ne peuvent pas g\u00e9rer, toutes sortes de plaintes commencent. Par exemple, un jour, on m'a dit d'arr\u00eater d'\u00e9crire du code parce que j'en \u00e9crivais trop, mettant en p\u00e9ril l'\u00e9quipe, et tout cela me semblait une blague : si toute l'\u00e9quipe restante dispara\u00eet et que je continue \u00e0 \u00e9crire du code, tu ne perds que la moiti\u00e9 de l'\u00e9quipe. D'un autre c\u00f4t\u00e9, si je continue \u00e0 coder et que tu perds la moiti\u00e9 de l'\u00e9quipe, cela semble \u00eatre une tr\u00e8s mauvaise gestion. Je n'y ai jamais vraiment r\u00e9fl\u00e9chi, je n'en ai jamais parl\u00e9, mais c'\u00e9tait quand m\u00eame quelque part dans mon esprit. \u00c0 l'arri\u00e8re-plan de ma conscience, je pensais : \u00ab Vous rigolez, non ? \u00bb. Donc, le plus grand probl\u00e8me \u00e9tait moi et mes relations avec les gens. Maintenant, je me comprends beaucoup mieux, j'ai longtemps \u00e9t\u00e9 lead technique chez les programmeurs, et maintenant je dis directement aux gens : tu sais, je suis comme je suis, et vous devrez faire avec \u2013 est-ce que \u00e7a vous d\u00e9range si je reste ici ? Et quand ils ont commenc\u00e9 \u00e0 g\u00e9rer cela, tout a fonctionn\u00e9. En fait, je ne suis ni mauvais ni bon, je n'ai aucune mauvaise intention ou aspiration \u00e9go\u00efste, c'est juste ma nature, et il faut juste vivre avec \u00e7a.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: R\u00e9cemment, tout le monde a commenc\u00e9 \u00e0 parler de la conscience de soi pour les introvertis, et en g\u00e9n\u00e9ral des soft skills. Que peut-on en dire ?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>Oui, c'\u00e9tait une prise de conscience et une le\u00e7on que j'ai tir\u00e9e de mon divorce avec ma femme. Ce que j'ai retenu de ce divorce, c'est une meilleure compr\u00e9hension de moi-m\u00eame. Ainsi, j'ai commenc\u00e9 \u00e0 comprendre les autres. Comprendre comment cette interaction fonctionne. Cela a entra\u00een\u00e9 des d\u00e9couvertes les unes apr\u00e8s les autres. J'ai pris conscience de qui je suis et de ce que je repr\u00e9sente. Ce que je fais : soit je me concentre sur la t\u00e2che, soit j'\u00e9vite le conflit, ou autre chose \u2013 et ce niveau de conscience de soi m'aide vraiment \u00e0 garder mon calme. Apr\u00e8s cela, tout devient beaucoup plus simple. Une chose que j'ai remarqu\u00e9e non seulement en moi, mais aussi chez d'autres programmeurs, c'est l'incapacit\u00e9 \u00e0 verbaliser des pens\u00e9es lorsque l'on est sous stress \u00e9motionnel. Par exemple, tu es en train de coder, tu es dans un \u00e9tat de flux, et l\u00e0 on arrive en courant et commence \u00e0 crier dans une crise en disant que quelque chose s'est cass\u00e9, et que des mesures extr\u00eames vont \u00eatre prises. Et tu ne peux m\u00eame pas dire un mot car tu es dans un \u00e9tat de stress \u00e9motionnel. Les connaissances acquises permettent de se pr\u00e9parer \u00e0 ce moment, de le vivre et de passer \u00e0 un plan de secours, apr\u00e8s quoi on peut d\u00e9j\u00e0 agir. Donc oui, lorsque tu commences \u00e0 r\u00e9aliser comment tout cela fonctionne \u2013 c'est un \u00e9v\u00e9nement \u00e9norme qui change la vie.\u00a0<br \/>\nJe n'ai pas pu trouver les bons mots moi-m\u00eame, mais je me souviens de la s\u00e9quence des actions. L'essence est que cette r\u00e9action est aussi physique que verbale, et tu as besoin d'espace. Un tel espace, dans le sens zen. C'est pr\u00e9cis\u00e9ment cela qu'il faut expliquer, puis imm\u00e9diatement se retirer \u2013 se retirer physiquement. Quand je suis silencieux, je peux traiter la situation sur le plan \u00e9motionnel. Au fur et \u00e0 mesure que l'adr\u00e9naline atteint le cerveau, te passant en mode \u00ab fuir ou combattre \u00bb, tu ne peux plus rien dire, non \u2013 maintenant tu es un idiot, un ing\u00e9nieur sur qui on peut s'acharner, incapable de donner une r\u00e9ponse digne ou m\u00eame d'arr\u00eater l'attaque, et l'attaquant peut librement continuer \u00e0 attaquer encore et encore. Il faut d'abord redevenir soi-m\u00eame, restaurer le contr\u00f4le, sortir du mode \u00ab fuir ou combattre \u00bb. <\/p>\n<p><\/p>\n<p>Et pour cela, il est n\u00e9cessaire d'avoir un espace verbal. Juste un espace libre. Si jamais on veut dire quelque chose, on peut simplement Affirmer cela, puis aller r\u00e9ellement trouver son \u00ab espace \u00bb : se promener dans un parc, se enfermer sous la douche - peu importe. L'essentiel est de se d\u00e9connecter temporairement de cette situation. D\u00e8s que tu te d\u00e9connectes, m\u00eame pendant quelques secondes, le contr\u00f4le revient, tu commences \u00e0 penser clairement. \u00ab Bien, je ne suis pas un idiot, je ne fais pas de choses stupides, je suis une personne plut\u00f4t utile \u00bb. Une fois que tu as r\u00e9ussi \u00e0 te convaincre, il est temps de passer \u00e0 l'\u00e9tape suivante : comprendre ce qui s'est pass\u00e9. Tu as \u00e9t\u00e9 attaqu\u00e9, l'attaque est venue d'o\u00f9 tu ne t'y attendais pas, c'\u00e9tait une embuscade l\u00e2che et injuste. C'est mal. La prochaine \u00e9tape consiste \u00e0 comprendre pourquoi l'attaquant avait besoin de cela. En effet, pourquoi ? Peut-\u00eatre parce qu'il est lui-m\u00eame en col\u00e8re ? Pourquoi est-il en col\u00e8re ? Par exemple, parce qu'il a rat\u00e9 quelque chose et ne peut pas accepter la responsabilit\u00e9 ? C'est par ce moyen qu'il faut traiter toute la situation avec pr\u00e9caution. Mais pour cela, il faut de l'espace pour man\u0153uvrer, un espace verbal. La toute premi\u00e8re \u00e9tape est de rompre le contact verbal. \u00c9viter la discussion verbale. L'annuler, s'en \u00e9loigner le plus rapidement possible. Si c'est une conversation t\u00e9l\u00e9phonique, repose simplement le combin\u00e9 - c'est une comp\u00e9tence que j'ai acquise lors de mes \u00e9changes avec mon ex-femme. Si la conversation n'aboutit \u00e0 rien de bon, dis simplement \u00ab au revoir \u00bb et raccroche. De l'autre c\u00f4t\u00e9 du combin\u00e9 : \u00ab blabla \u00bb, tu r\u00e9ponds : \u00ab d'accord, salut ! \u00bb et tu raccroches. Tu interromps simplement la conversation. Cinq minutes plus tard, quand ta capacit\u00e9 \u00e0 penser clairement te revient, que tu as l\u00e9g\u00e8rement refroidi, il devient possible de r\u00e9fl\u00e9chir \u00e0 ce qui s'est r\u00e9ellement pass\u00e9 et ce qui va suivre. Et commencer \u00e0 formuler une r\u00e9ponse r\u00e9fl\u00e9chie, plut\u00f4t que de simplement r\u00e9agir \u00e9motionnellement. Pour moi, le v\u00e9ritable tournant dans la prise de conscience de soi a \u00e9t\u00e9 que dans des situations stressantes \u00e9motionnellement, je ne peux pas parler. Sortir de cet \u00e9tat, r\u00e9fl\u00e9chir et planifier comment r\u00e9pondre et compenser les probl\u00e8mes - ce sont les bonnes \u00e9tapes lorsque tu ne peux pas parler. La fa\u00e7on la plus simple est de fuir la situation dans laquelle se manifeste le stress \u00e9motionnel et simplement de cesser d'y participer. Apr\u00e8s cela, tu acquiers la capacit\u00e9 de penser, lorsque tu peux penser, la possibilit\u00e9 de parler, et ainsi de suite.<\/p>\n<p><\/p>\n<p>En fait, devant le tribunal, l'avocat de la partie adverse essaie de faire \u00e7a avec toi \u2013 maintenant, c'est clair pourquoi. Parce qu'il a la possibilit\u00e9 de te submerger au point que tu ne peux m\u00eame plus prononcer ton nom, par exemple. Dans le sens le plus direct, tu ne peux pas parler. Si cela t'arrive et que tu sais que tu te retrouveras dans un endroit o\u00f9 des batailles verbales font rage, comme un tribunal, tu peux venir avec ton avocat. L'avocat se battra pour toi et mettra fin \u00e0 l'attaque verbale, et ce sera tout \u00e0 fait l\u00e9gal, et tu retrouveras ton espace zen perdu. Par exemple, il m'est arriv\u00e9 plusieurs fois de devoir appeler ma famille, le juge a \u00e9t\u00e9 assez amical \u00e0 ce sujet, mais l'avocat de l'autre partie criait et criait sur moi, je ne pouvais m\u00eame pas en placer une. Dans de tels cas, l'utilisation d'un interm\u00e9diaire fonctionne le mieux pour moi. L'interm\u00e9diaire interrompt toute cette pression qui s'abat sur toi de mani\u00e8re continue, tu retrouves cet espace zen n\u00e9cessaire, et avec lui, la capacit\u00e9 de parler revient. C'est un domaine de connaissance dans lequel il faut beaucoup apprendre, beaucoup d\u00e9couvrir en soi, et tout cela se transforme en d\u00e9cisions strat\u00e9giques de haut niveau, diff\u00e9rentes pour diff\u00e9rentes personnes. Certains n'ont pas les probl\u00e8mes d\u00e9crits ci-dessus, en g\u00e9n\u00e9ral, ils n'en ont pas chez les professionnels de la vente. Toutes ces personnes qui gagnent leur vie avec des mots \u2013 des chanteurs c\u00e9l\u00e8bres, des po\u00e8tes, des figures religieuses et des politiciens, ils ont toujours quelque chose \u00e0 dire. Ils n'ont pas ces probl\u00e8mes, mais moi, je les ai.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: C'\u00e9tait... inattendu. Tr\u00e8s bien, nous avons d\u00e9j\u00e0 beaucoup discut\u00e9 et il est temps de conclure cette interview. Nous nous rencontrerons certainement \u00e0 la conf\u00e9rence et pourrons poursuivre ce dialogue. \u00c0 la rencontre sur Hydra !<\/p>\n<p><\/p>\n<blockquote><p>Tu pourras continuer \u00e0 discuter avec Cliff \u00e0 la conf\u00e9rence Hydra 2019, qui se tiendra les 11 et 12 juillet 2019 \u00e0 Saint-P\u00e9tersbourg. Il viendra avec une pr\u00e9sentation <noindex><a rel=\"nofollow\" href=\"https:\/\/hydraconf.com\/2019\/talks\/2jix5mst7iduyp9linqhfj\/?utm_source=habr&amp;utm_medium=45871\">\u00abL'exp\u00e9rience de la m\u00e9moire transactionnelle mat\u00e9rielle d'Azul\u00bb<\/a><\/noindex>. Tickets disponibles \u00e0 l'achat <noindex><a rel=\"nofollow\" href=\"https:\/\/hydraconf.ru\/?utm_source=habr&amp;utm_medium=458718\">sur le site officiel<\/a><\/noindex>.<\/p><\/blockquote>\n<p>Source : <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/jugru\/blog\/458718\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041a\u043b\u0438\u0444\u0444 \u041a\u043b\u0438\u043a \u2014 CTO \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Cratus (IoT \u0441\u0435\u043d\u0441\u043e\u0440\u044b \u0434\u043b\u044f \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432), \u043e\u0441\u043d\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438 \u0441\u043e\u043e\u0441\u043d\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0442\u0430\u0440\u0442\u0430\u043f\u043e\u0432 (\u0432\u043a\u043b\u044e\u0447\u0430\u044f Rocket Realtime School, Neurensic \u0438 H2O.ai) \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u043c\u0438 \u044d\u043a\u0437\u0438\u0442\u0430\u043c\u0438. \u041a\u043b\u0438\u0444\u0444 \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0441\u0432\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0432 15 \u043b\u0435\u0442 (Pascal \u0434\u043b\u044f TRS Z-80)! \u041d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u043d\u0430\u0434 \u04212 \u0432 Java (the Sea of Nodes IR). \u042d\u0442\u043e\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u043e\u043a\u0430\u0437\u0430\u043b [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-35851","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041a\u043b\u0438\u0444\u0444 \u041a\u043b\u0438\u043a \u2014.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0411\u043e\u043b\u044c\u0448\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e \u0441 \u041a\u043b\u0438\u0444\u0444\u043e\u043c \u041a\u043b\u0438\u043a\u043e\u043c \u2014 \u043e\u0442\u0446\u043e\u043c JIT-\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0432 Java | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041a\u043b\u0438\u0444\u0444 \u041a\u043b\u0438\u043a \u2014.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:07:03+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:07:03+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Grande interview avec Cliff Click \u2013 le p\u00e8re de la compilation JIT en Java | ProHoster","description":"Cliff Click \u2013.","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0411\u043e\u043b\u044c\u0448\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e \u0441 \u041a\u043b\u0438\u0444\u0444\u043e\u043c \u041a\u043b\u0438\u043a\u043e\u043c \u2014 \u043e\u0442\u0446\u043e\u043c JIT-\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0432 Java | ProHoster","og:description":"\u041a\u043b\u0438\u0444\u0444 \u041a\u043b\u0438\u043a \u2014.","og:url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:07:03+00:00","article:modified_time":"2019-10-31T19:07:03+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"35851","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 01:01:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:55:25","updated":"2026-01-22 01:01:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/35851","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=35851"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/35851\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=35851"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=35851"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=35851"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}