{"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\/informatique\/demarrage-jvm-8-vs-9\/","title":{"rendered":"D\u00e9marrage JVM 8 vs 9"},"content":{"rendered":"<p><\/p>\n<h2>Introduction<\/h2>\n<p>En parcourant la mailing liste d&#8217;open JDK (core-lib-dev) j&#8217;ai vu plusieurs threads de mail \u00e0 propos d&#8217;optimisation de temps de d\u00e9marrage et d&#8217;occupation m\u00e9moire d&#8217;une JVM &#8220;<em>minimale<\/em>&#8220;.<\/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&#8217;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\u00a0176). Pour r\u00e9aliser ces tests j&#8217;ai utilis\u00e9 les images docker\u00a0azul\/zulu-openjdk:8u51 et\u00a0azul\/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(&amp;quot;Hello World&amp;quot;);\n    }\n}\npublic class HelloWorldLambda {\n    public static void main(String[] args) {\n        Runnable hello = () -&amp;amp;gt; System.out.println(&amp;quot;Hello lambda world&amp;quot;);\n        hello.run();\n    }\n}\n<\/pre>\n<p>J&#8217;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&#8217;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&#8217;utilisation m\u00e9moire pour un simple HelloWorld, je me suis souvenu d&#8217;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 -XX:+UseSerialGC HelloWorld\nreal    0m0.084s\nuser    0m0.077s\nsys     0m0.014s\ntime java -Xmx16m -Xms16m -XX:+UseSerialGC -XX:-TieredCompilation -XX:+UseSerialGC HelloWorldLambda\nreal    0m0.172s\nuser    0m0.197s\nsys     0m0.018s\n<\/pre>\n<p><strong>Constatation :<\/strong> Le temps de d\u00e9marrage n&#8217;est pas significativement r\u00e9duit dans le cas standard (mais l&#8217;est avec lambda) mais l&#8217;occupation m\u00e9moire l&#8217;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&#8217;optimisation du d\u00e9marrage de la JVM, le temps de d\u00e9marrage est moins bon hors lambda mais meilleur avec lambda qu&#8217;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 -XX:+UseSerialGC HelloWorld\nreal    0m0.152s\nuser    0m0.143s\nsys     0m0.022s\ntime java -Xmx16m -Xms16m -XX:+UseSerialGC -XX:-TieredCompilation -XX:+UseSerialGC 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&#8217;\u00e9volue pas beaucoup mais l&#8217;utilisation m\u00e9moire baisse drastiquement et retourne quasiment au m\u00eame niveau qu&#8217;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&#8217;est donc bien l&#8217;utilisation de G1 par d\u00e9faut dans Java 9 qui est la cause de l&#8217;augmentation de l&#8217;utilisation m\u00e9moire plus importante en 9 qu&#8217;en 8.<\/p>\n<h2>Conclusion<\/h2>\n<p>Premi\u00e8re constatation : L&#8217;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&#8217;Oracle Java 9 d\u00e9marre plus lentement que Java 8 et utilise plus de m\u00e9moire. Certain choix entre en contradiction directe avec l&#8217;optimisation du d\u00e9marrage d&#8217;une JVM (entre autre, le passage de G1 comme garbage collector par d\u00e9faut).<\/p>\n<p>Troisi\u00e8me constatation : L&#8217;\u00e9cart entre code utilisant et n&#8217;utilisant pas les lambda s&#8217;est \u00e9norm\u00e9ment r\u00e9duit entre Java 8 et Java 9<\/p>\n<p>Attention : le protocole de test utilis\u00e9 ici n&#8217;\u00e9tait peut-\u00eatre pas tr\u00e8s rigoureux, lancer plusieurs fois un process via la commande time n&#8217;est pas la panac\u00e9e. De plus le d\u00e9veloppent de Java 9 n&#8217;est pas encore termin\u00e9, on peut esp\u00e9rer que la version finale comblera en partie ou totalement l&#8217;\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&#8217;open JDK (core-lib-dev) j&#8217;ai vu plusieurs threads de mail \u00e0 propos d&#8217;optimisation de temps de d\u00e9marrage et d&#8217;occupation m\u00e9moire d&#8217;une JVM &#8220;minimale&#8220;. Ce travail a \u00e9t\u00e9 r\u00e9alis\u00e9 en grande partie par Claes Redestad (Oracle) lors du d\u00e9veloppement de Java 9. J&#8217;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\/informatique\/demarrage-jvm-8-vs-9\/\"> Read More<span class=\"screen-reader-text\">  Read More<\/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\/informatique\/java-16-quoi-de-neuf\/","url_meta":{"origin":712,"position":0},"title":"Java 16 : what&#8217;s new ?","author":"admin","date":"Friday January 29th, 2021","format":false,"excerpt":"Now that Java 16 is features complete (Rampdown Phase Two at the day of writing), it\u2019s time to walk throught all the functionalities that brings to us, developers, this new version. This article is part of a series on what\u2019s new on the last versions of Java, for those who\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1090,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/quarkus-jlink-et-application-class-data-sharing-appcds\/","url_meta":{"origin":712,"position":1},"title":"Quarkus, jlink and Application Class Data Sharing (AppCDS)","author":"admin","date":"Friday May 29th, 2020","format":false,"excerpt":"Quarkus is optimized to start quickly and have a very small memory footprint. This is true when deploying in a standard JVM but even more so when deploying our application as a native executable via GraalVM. Quarkus greatly facilitates the creation of a native executable, thanks to this, a Quarkus\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/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\/informatique\/java-24-quoi-de-neuf\/","url_meta":{"origin":712,"position":2},"title":"Java 24 : what&#8217;s new?","author":"admin","date":"Friday January 10th, 2025","format":false,"excerpt":"Now that Java 24 is features complete (Rampdown Phase One at the day of writing), it\u2019s time to walk through all the functionalities that bring to us, developers, this new version. This article is part of a series on what\u2019s new on the last versions of Java, for those who\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1068,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/j-ai-teste-java-google-cloud-functions-aplha\/","url_meta":{"origin":712,"position":3},"title":"(Fran\u00e7ais) J&#8217;ai test\u00e9 Java Google Cloud Functions Alpha","author":"admin","date":"Wednesday May  6th, 2020","format":false,"excerpt":"Sorry, this entry is only available in Fran\u00e7ais.","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1258,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/profiler-une-application-java-dans-un-conteneur-deploye-dans-kubernetes-avec-jfr-java-flight-recorder\/","url_meta":{"origin":712,"position":4},"title":"(Fran\u00e7ais) Profiler une application Java dans un conteneur d\u00e9ploy\u00e9 dans kubernetes avec JFR &#8211; Java Flight Recorder","author":"admin","date":"Monday April 12th, 2021","format":false,"excerpt":"Sorry, this entry is only available in Fran\u00e7ais.","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1684,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/java-21-quoi-de-neuf\/","url_meta":{"origin":712,"position":5},"title":"Java 21: what&#8217;s new ?","author":"admin","date":"Tuesday August  8th, 2023","format":false,"excerpt":"Now that Java 21 is features complete (Rampdown Phase Two at the day of writing), it\u2019s time to walk through all the functionalities that bring to us, developers, this new version. This article is part of a series on what\u2019s new on the last versions of Java, for those who\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/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\/wp-json\/wp\/v2\/posts\/712","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/comments?post=712"}],"version-history":[{"count":0,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts\/712\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/media?parent=712"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/categories?post=712"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/tags?post=712"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}