{"id":712,"date":"2017-08-31T14:53:31","date_gmt":"2017-08-31T12:53:31","guid":{"rendered":"http:\/\/www.loicmathieu.fr\/wordpress\/?p=712"},"modified":"2017-10-13T17:13:10","modified_gmt":"2017-10-13T15:13:10","slug":"demarrage-jvm-8-vs-9","status":"publish","type":"post","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/demarrage-jvm-8-vs-9\/","title":{"rendered":"D\u00e9marrage JVM 8 vs 9"},"content":{"rendered":"<p><h2>Introduction<\/h2>\nEn parcourant la mailing liste d&rsquo;open JDK (core-lib-dev) j&rsquo;ai vu plusieurs threads de mail \u00e0 propos d&rsquo;optimisation de temps de d\u00e9marrage et d&rsquo;occupation m\u00e9moire d&rsquo;une JVM \u00ab\u00a0<em>minimale<\/em>\u00ab\u00a0.<\/p>\n<p>Ce travail a \u00e9t\u00e9 r\u00e9alis\u00e9 en grande partie par Claes Redestad (Oracle) lors du d\u00e9veloppement de Java 9.<\/p>\n<p>J&rsquo;ai donc d\u00e9cid\u00e9 de tester la diff\u00e9rence entre un HelloWorld (en version standard et avec utilisation de Lambda) entre Java 8 (update 51 pour ne pas risquer de backport des optimisations en question sur cette version) et Java 9 (ea build&nbsp;176). Pour r\u00e9aliser ces tests j&rsquo;ai utilis\u00e9 les images docker&nbsp;azul\/zulu-openjdk:8u51 et&nbsp;azul\/zulu-openjdk:9ea et les deux classes suivantes :<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class HelloWorld {\n    public static void main(String[] args) {\n        System.out.println(\"Hello World\");\n    }\n}\npublic class HelloWorldLambda {\n    public static void main(String[] args) {\n        Runnable hello = () -&gt; System.out.println(\"Hello lambda world\");\n        hello.run();\n    }\n}\n<\/pre>\n<p>J&rsquo;ai ensuite utilis\u00e9 la commande Linux <strong>time<\/strong> pour conna\u00eetre le temps de traitement et la fonctionnalit\u00e9 de <strong>Native Memory Tracking<\/strong> de Java pour conna\u00eetre la m\u00e9moire allou\u00e9e.<\/p>\n<h2>Java 8<\/h2>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ntime java HelloWorld\nreal    0m0.085s\nuser    0m0.078s\nsys     0m0.019s\ntime java HelloWorldLambda\nreal    0m0.185s\nuser    0m0.236s\nsys     0m0.032s\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\njava -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary \\\n     -XX:+PrintNMTStatistics -Xmx16m -Xms16m HelloWorld\nTotal: reserved=1356124KB, committed=57156KB\njava -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary \\\n     -XX:+PrintNMTStatistics -Xmx16m -Xms16m HelloWorldLambda\nTotal: reserved=1358869KB, committed=59901KB\n<\/pre>\n<p><strong>Constatation<\/strong> : une JVM \u00e7a d\u00e9marre vite (moins de 100ms) mais \u00e7a utilise quand m\u00eame plus de 57Mo de RAM juste pour un HelloWorld! L&rsquo;utilisation de Lambda implique un temps de d\u00e9marrage plus que doubl\u00e9 et un overhead de m\u00e9moire de 2Mo.<\/p>\n<p>Hum, 57Mo quand m\u00eame d&rsquo;utilisation m\u00e9moire pour un simple HelloWorld, je me suis souvenu d&rsquo;un article fort int\u00e9ressant sur le sujet \u00e9crit par Alexey Shipilev, je me suis replong\u00e9 dedans pour creuser la question : <a href=\"https:\/\/shipilev.net\/jvm-anatomy-park\/12-native-memory-tracking\/\"><a href=\"https:\/\/shipilev.net\/jvm-anatomy-park\/12-native-memory-tracking\/\">https:\/\/shipilev.net\/jvm-anatomy-park\/12-native-memory-tracking\/<\/a><\/a> et ai ajout\u00e9 quelques options au d\u00e9marrage de ma JVM :<\/p>\n<ul><li>SerialGC : le garbage collector qui d\u00e9marre le plus vite et n\u00e9cessite le moins de m\u00e9moire<\/li>\n\n<li>Une heap \u00e0 16Mo : largement suffisant pour un HelloWorld<\/li>\n\n<li>D\u00e9sactivation du TieredCompilation qui lui aussi n\u00e9cessite plus de m\u00e9moire<\/li>\n<\/ul>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\njava -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics \\\n     -Xmx16m -Xms16m -XX:+UseSerialGC -XX:-TieredCompilation HelloWorld\nTotal: reserved=1134567KB, committed=35279KB\njava -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics \\\n     -Xmx16m -Xms16m -XX:+UseSerialGC -XX:-TieredCompilation HelloWorldLambda\nTotal: reserved=1135918KB, committed=36630KB\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ntime java -Xmx16m -Xms16m -XX:+UseSerialGC -XX:-TieredCompilation HelloWorld\nreal    0m0.084s\nuser    0m0.077s\nsys     0m0.014s\ntime java -Xmx16m -Xms16m -XX:+UseSerialGC -XX:-TieredCompilation HelloWorldLambda\nreal    0m0.172s\nuser    0m0.197s\nsys     0m0.018s\n<\/pre>\n<p><strong>Constatation :<\/strong> Le temps de d\u00e9marrage n&rsquo;est pas significativement r\u00e9duit dans le cas standard (mais l&rsquo;est avec lambda) mais l&rsquo;occupation m\u00e9moire l&rsquo;est grandement. On gagne pr\u00e8s de 20Mo gr\u00e2ce ces options de d\u00e9marrage.<\/p>\n<h2>Java 9<\/h2>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ntime java HelloWorld\nreal    0m0.161s\nuser    0m0.177s\nsys     0m0.048s\ntime java HelloWorldLambda\nHello lambda world\nreal    0m0.199s\nuser    0m0.228s\nsys     0m0.042s\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\njava -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary \\\n     -XX:+PrintNMTStatistics -Xmx16m -Xms16m HelloWorld\nTotal: reserved=1389612KB, committed=97536KB\njava -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary \\\n     -XX:+PrintNMTStatistics -Xmx16m -Xms16m HelloWorldLambda\nTotal: reserved=1390008KB, committed=98188KB\n<\/pre>\n<p><strong>Constatation :<\/strong> En Java 9, malgr\u00e9 le travail d&rsquo;optimisation du d\u00e9marrage de la JVM, le temps de d\u00e9marrage est moins bon hors lambda mais meilleur avec lambda qu&rsquo;en Java 8. Il reste donc du travail \u00e0 faire, JPMS (project Jigsaw) est peut-\u00eatre le fautif ici. C\u00f4t\u00e9 m\u00e9moire, il y a une forte augmentation.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\njava -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics \\\n     -Xmx16m -Xms16m -XX:+UseSerialGC -XX:-TieredCompilation HelloWorld\nTotal: reserved=1137041KB, committed=38117KB\njava -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics \\\n     -Xmx16m -Xms16m -XX:+UseSerialGC -XX:-TieredCompilation HelloWorldLambda\nTotal: reserved=1137178KB, committed=38510KB\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ntime java -Xmx16m -Xms16m -XX:+UseSerialGC -XX:-TieredCompilation HelloWorld\nreal    0m0.152s\nuser    0m0.143s\nsys     0m0.022s\ntime java -Xmx16m -Xms16m -XX:+UseSerialGC -XX:-TieredCompilation HelloWorldLambda\nreal    0m0.202s\nuser    0m0.188s\nsys     0m0.020s\n<\/pre>\n<p><strong>Constatation :<\/strong> En optimisant les options JVM, le temps de d\u00e9marrage n&rsquo;\u00e9volue pas beaucoup mais l&rsquo;utilisation m\u00e9moire baisse drastiquement et retourne quasiment au m\u00eame niveau qu&rsquo;en Java 8 dans la m\u00eame configuration. Sachant que Java 9 vient avec Le garbage collector G1 par d\u00e9faut (au lieu du Parallel GC), la consommation excessive doit provenir de celui-ci.<\/p>\n<p>Essayons donc de v\u00e9rifier en activant le ParallelGC qui \u00e9tait le d\u00e9faut en Java 8.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\njava -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics \\\n     -Xmx16m -Xms16m -XX:+UseParallelOldGC -XX:-TieredCompilation HelloWorld\nTotal: reserved=1157722KB, committed=58798KB\n\njava -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics \\\n     -Xmx16m -Xms16m -XX:+UseParallelOldGC -XX:-TieredCompilation HelloWorldLambda\nTotal: reserved=1157860KB, committed=59192KB\n<\/pre>\n<p><strong>Constatation :<\/strong> C&rsquo;est donc bien l&rsquo;utilisation de G1 par d\u00e9faut dans Java 9 qui est la cause de l&rsquo;augmentation de l&rsquo;utilisation m\u00e9moire plus importante en 9 qu&rsquo;en 8.<\/p>\n<h2>Conclusion<\/h2>\n<p>Premi\u00e8re constatation : L&rsquo;id\u00e9e pr\u00e9con\u00e7ue que java est lent \u00e0 d\u00e9marrer et ne peux \u00eatre utilis\u00e9 pour des applications de type ligne de commande est erron\u00e9e! Une JVM d\u00e9marre en moins de 100ms!<\/p>\n<p>Deuxi\u00e8me constatation : Malgr\u00e9 tout le travail fait par les ing\u00e9nieurs d&rsquo;Oracle Java 9 d\u00e9marre plus lentement que Java 8 et utilise plus de m\u00e9moire. Certain choix entre en contradiction directe avec l&rsquo;optimisation du d\u00e9marrage d&rsquo;une JVM (entre autre, le passage de G1 comme garbage collector par d\u00e9faut).<\/p>\n<p>Troisi\u00e8me constatation : L&rsquo;\u00e9cart entre code utilisant et n&rsquo;utilisant pas les lambda s&rsquo;est \u00e9norm\u00e9ment r\u00e9duit entre Java 8 et Java 9<\/p>\n<p>Attention : le protocole de test utilis\u00e9 ici n&rsquo;\u00e9tait peut-\u00eatre pas tr\u00e8s rigoureux, lancer plusieurs fois un process via la commande time n&rsquo;est pas la panac\u00e9e. De plus le d\u00e9veloppent de Java 9 n&rsquo;est pas encore termin\u00e9, on peut esp\u00e9rer que la version finale comblera en partie ou totalement l&rsquo;\u00e9cart de temps de d\u00e9marrage entre une JVM 8 et 9. A tester donc avec une version finale.<\/p>","protected":false},"excerpt":{"rendered":"<p>Introduction En parcourant la mailing liste d&rsquo;open JDK (core-lib-dev) j&rsquo;ai vu plusieurs threads de mail \u00e0 propos d&rsquo;optimisation de temps de d\u00e9marrage et d&rsquo;occupation m\u00e9moire d&rsquo;une JVM \u00ab\u00a0minimale\u00ab\u00a0. Ce travail a \u00e9t\u00e9 r\u00e9alis\u00e9 en grande partie par Claes Redestad (Oracle) lors du d\u00e9veloppement de Java 9. J&rsquo;ai donc d\u00e9cid\u00e9 de tester la diff\u00e9rence entre un HelloWorld (en version standard et avec utilisation de Lambda) entre Java 8 (update 51 pour ne pas risquer de backport des optimisations en question sur&#8230;<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/demarrage-jvm-8-vs-9\/\">Lire la suite<span class=\"screen-reader-text\"> Lire la suite<\/span><\/a><\/p><\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":4,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[9],"tags":[],"class_list":["post-712","post","type-post","status-publish","format-standard","hentry","category-informatique"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":1215,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/java-16-quoi-de-neuf\/","url_meta":{"origin":712,"position":0},"title":"Java 16 : quoi de neuf ?","author":"admin","date":"vendredi 29 janvier 2021","format":false,"excerpt":"Maintenant que Java 16 est features complete (Rampdown Phase Two au jour d\u2019\u00e9criture de l\u2019article), c\u2019est le moment de faire le tour des fonctionnalit\u00e9s qu\u2019apporte cette nouvelle version, \u00e0 nous, les d\u00e9veloppeurs. Cet article fait partie d\u2019une suite d\u2019article sur les nouveaut\u00e9s des derni\u00e8res versions de Java, pour ceux qui\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1090,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/quarkus-jlink-et-application-class-data-sharing-appcds\/","url_meta":{"origin":712,"position":1},"title":"Quarkus, jlink et Application Class Data Sharing (AppCDS)","author":"admin","date":"vendredi 29 mai 2020","format":false,"excerpt":"Quarkus est optimis\u00e9 pour d\u00e9marrer rapidement et avoir une empreinte m\u00e9moire tr\u00e8s faible. Ceci est vrai en d\u00e9ployant dans une JVM standard mais encore plus en d\u00e9ployant notre application comme un ex\u00e9cutable natif via GraalVM. Quarkus facilite grandement la cr\u00e9ation d\u2019ex\u00e9cutable natif, gr\u00e2ce \u00e0 \u00e7a, une application Quarkus d\u00e9marre en\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/quarkus_metrics_graphic_bootmem_wide-1024x473.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/quarkus_metrics_graphic_bootmem_wide-1024x473.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/quarkus_metrics_graphic_bootmem_wide-1024x473.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":1877,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/java-24-quoi-de-neuf\/","url_meta":{"origin":712,"position":2},"title":"Java 24 : quoi de neuf ?","author":"admin","date":"vendredi 10 janvier 2025","format":false,"excerpt":"Maintenant que Java 24 est features complete (Rampdown Phase One au jour d\u2019\u00e9criture de l\u2019article), c\u2019est le moment de faire le tour des fonctionnalit\u00e9s qu\u2019apporte cette nouvelle version, \u00e0 nous, les d\u00e9veloppeurs. Cet article fait partie d\u2019une suite d\u2019article sur les nouveaut\u00e9s des derni\u00e8res versions de Java, pour ceux qui\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1068,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/j-ai-teste-java-google-cloud-functions-aplha\/","url_meta":{"origin":712,"position":3},"title":"J&rsquo;ai test\u00e9 Java Google Cloud Functions Alpha","author":"admin","date":"mercredi  6 mai 2020","format":false,"excerpt":"J'ai test\u00e9 les Java Google Cloud Functions en Alpha. Jusqu'ici, les Cloud Functions de Google n'\u00e9taient impl\u00e9mentables qu'en NodeJs, Go ou Python. Mais Google est en train de pr\u00e9parer l'ouverture d'un runtime Java (8 et 11), que j'ai pu tester en alpha release priv\u00e9e (pour s'inscrire, c'est ici). Apr\u00e8s inscription\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1258,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/profiler-une-application-java-dans-un-conteneur-deploye-dans-kubernetes-avec-jfr-java-flight-recorder\/","url_meta":{"origin":712,"position":4},"title":"Profiler une application Java dans un conteneur d\u00e9ploy\u00e9 dans kubernetes avec JFR &#8211; Java Flight Recorder","author":"admin","date":"lundi 12 avril 2021","format":false,"excerpt":"La plupart des clients chez lesquels j'interviens aujourd'hui utilisent Kubernetes pour d\u00e9ployer leurs applications. Bien que Kubernetes soit un super outil, si on a besoin de ce type d'outil (qui est une discussion dans laquelle je ne rentrerais pas ici), il peut apporter une certaine complexit\u00e9 quant aux moyens de\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1684,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/java-21-quoi-de-neuf\/","url_meta":{"origin":712,"position":5},"title":"Java 21 : quoi de neuf ?","author":"admin","date":"mardi  8 ao\u00fbt 2023","format":false,"excerpt":"Maintenant que Java 21 est features complete (Rampdown Phase Two au jour d\u2019\u00e9criture de l\u2019article), c\u2019est le moment de faire le tour des fonctionnalit\u00e9s qu\u2019apporte cette nouvelle version, \u00e0 nous, les d\u00e9veloppeurs. Cet article fait partie d\u2019une suite d\u2019article sur les nouveaut\u00e9s des derni\u00e8res versions de Java, pour ceux qui\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"Java Collection API hierarchy","src":"https:\/\/i0.wp.com\/cr.openjdk.org\/~smarks\/collections\/SequencedCollectionDiagram20220216.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/cr.openjdk.org\/~smarks\/collections\/SequencedCollectionDiagram20220216.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/cr.openjdk.org\/~smarks\/collections\/SequencedCollectionDiagram20220216.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/cr.openjdk.org\/~smarks\/collections\/SequencedCollectionDiagram20220216.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/cr.openjdk.org\/~smarks\/collections\/SequencedCollectionDiagram20220216.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/cr.openjdk.org\/~smarks\/collections\/SequencedCollectionDiagram20220216.png?resize=1400%2C800&ssl=1 4x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts\/712","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/comments?post=712"}],"version-history":[{"count":0,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts\/712\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/media?parent=712"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/categories?post=712"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/tags?post=712"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}