{"id":1030,"date":"2020-04-21T10:53:21","date_gmt":"2020-04-21T08:53:21","guid":{"rendered":"https:\/\/www.loicmathieu.fr\/wordpress\/?p=1030"},"modified":"2020-12-01T19:56:32","modified_gmt":"2020-12-01T18:56:32","slug":"for-vs-stream","status":"publish","type":"post","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/for-vs-stream\/","title":{"rendered":"For vs Stream"},"content":{"rendered":"<p>Cela faisait longtemps que je n&rsquo;avais pas \u00e9crit un article de blog et pourtant, pour cause de confinement, j&rsquo;ai du temps pour le faire!<\/p>\n<p>N&rsquo;ayant pas d&rsquo;id\u00e9e, j&rsquo;ai demand\u00e9 \u00e0 ma twitosph\u00e8re de m&rsquo;en donner, et j&rsquo;ai eu une r\u00e9ponse int\u00e9ressante :<\/p>\n<blockquote class=\"twitter-tweet\">\n<p dir=\"ltr\" lang=\"fr\">Les diff\u00e9rences de perf entre stream et for classique ? On en a parl\u00e9 y&rsquo;a longtemps, mais j&rsquo;avais fait une session de micro bench avec JMH qui montrait que les &lsquo;for&rsquo; \u00e9taient plus performants que les streams.<\/p>\n\u2014 J\u00e9r\u00e9my Thulliez (@JeremyThulliez) <a href=\"https:\/\/twitter.com\/JeremyThulliez\/status\/1250028611136114690?ref_src=twsrc%5Etfw\">April 14, 2020<\/a><\/blockquote>\n<a href=\"https:\/\/platform.twitter.com\/widgets.js\">https:\/\/platform.twitter.com\/widgets.js<\/a>\n<p>Voici donc un article parlant des diff\u00e9rences de performance entre une boucle for et un Stream Java.<\/p>\n<p>Tout d&rsquo;abord, parlons un peu de benchmark. Comme on veut comparer les performances d&rsquo;une boucle for et des Stream en Java, il nous faut un outil qui permet de r\u00e9aliser des micro-benchmarks de mani\u00e8re pertinente. En effet, quand on r\u00e9alise des micro-benchmarks, on peut rencontrer pas mal de soucis quand ce que l&rsquo;on veut mesurer est en dessous de la dizaine de microsecondes : un simple passage d&rsquo;un garbage collector par exemple peut rendre la mesure inop\u00e9rante. Il faut aussi correctement pr\u00e9-chauffer la JVM pour tenir compte de l&rsquo;effet du Just In Time Compiler (le JIT), sans parler de mesurer correctement le temps (et non, <code>System.currentTimeInMillis()<\/code> n&rsquo;est pas l\u2019apanage ici).<\/p>\n<p>Pour parer \u00e0 tous ces soucis, il n&rsquo;y a qu&rsquo;une seule solution, <a href=\"https:\/\/openjdk.java.net\/projects\/code-tools\/jmh\/\" rel=\"noopener noreferrer\" target=\"_blank\">JMH &#8211; The Java Microbenchmark Harness<\/a>. Cet outil nous permet d&rsquo;\u00e9crire des micro-benchmarks pertinents en tenant compte des caract\u00e9ristiques internes de la JVM. Il offre aussi des outils int\u00e9gr\u00e9s pour analyser les performances de nos tests (profiler, disassembler, &#8230;). Si vous ne connaissez pas JMH, vous pouvez vous r\u00e9f\u00e9rez \u00e0 cet article : <a href=\"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/introduction-a-jmh-java-microbenchmark-harness\/\" rel=\"noopener noreferrer\" target=\"_blank\">INTRODUCTION \u00c0 JMH \u2013 JAVA MICROBENCHMARK HARNESS<\/a>.<\/p>\n<p>Tous les tests ont \u00e9t\u00e9 ex\u00e9cut\u00e9s sur mon laptop : Intel(R) Core(TM) i7-8750H 6 coeurs (12 avec hyperthreading) &#8211; Ubuntu 19.10.<\/p>\n<h2>Benchmark 1 : \u00e0 vide<\/h2>\n<p>Pour notre premier test, comparons les performances <em>\u00e0 vide<\/em> via un test le plus simple possible, que l&rsquo;on va ex\u00e9cuter sur une liste \u00e0 taille variable (10, 1 000, 10 000 \u00e9l\u00e9ments).<\/p>\n<pre>\n    \/\/ the test will be done for 10, 1000 and 10000 elements\n    @Param({\"10\", \"1000\", \"10000\"}) \n    int size;\n\n    List\n list;\n\n    @Setup\n    public void setup() { \/\/ we setup the test with the test data\n        list = new ArrayList(size);\n        for (int i = 0; i  bh.consume(i));\n    }\n<\/pre>\n<p>Quand on lance un benchmark via JMH, le warning suivant est affich\u00e9, merci d&rsquo;en tenir compte ;)<\/p>\n<blockquote>\nREMEMBER: The numbers below are just data. \nTo gain reusable insights, you need to follow up on why the numbers are the way they are. \nUse profilers (see -prof, -lprof), design factorial experiments, perform baseline and negative tests that provide experimental control, make sure the benchmarking environment is safe on JVM\/OS\/HW level, ask for reviews from the domain experts.\nDo not assume the numbers tell you what you want them to tell.\n<\/blockquote>\n<p>Et voici les r\u00e9sultats en nanoseconde par op\u00e9ration (le plus bas est le meilleur) avec la JVM OpenJdk 11.0.5.<\/p>\n<pre>\nForVsStream.testForLoop_doNothing                  10  avgt    5      46,715 \u00b1     4,581  ns\/op\nForVsStream.testForLoop_doNothing                1000  avgt    5    4581,216 \u00b1   355,653  ns\/op\nForVsStream.testForLoop_doNothing               10000  avgt    5   45320,910 \u00b1   670,446  ns\/op\nForVsStream.testStream_doNothing                   10  avgt    5      51,563 \u00b1     3,682  ns\/op\nForVsStream.testStream_doNothing                 1000  avgt    5    3634,718 \u00b1   513,237  ns\/op\nForVsStream.testStream_doNothing                10000  avgt    5   36757,820 \u00b1  2956,085  ns\/op\n\n<\/pre>\n<p>Pour de petite valeur de liste, l&rsquo;utilisation d&rsquo;une boucle for est plus rapide, mais pour des valeurs plus importante (mais toujours assez petite), les Stream sont plus performants !<\/p>\n<p>La diff\u00e9rence pour la plus petite valeur d&rsquo;it\u00e9ration s&rsquo;explique facilement, l\u2019ex\u00e9cution d&rsquo;un Stream n\u00e9cessite la cr\u00e9ation d&rsquo;objets Java et celle-ci a un co\u00fbt qui est important au regard du co\u00fbt d&rsquo;ex\u00e9cution quand il y a peu d&rsquo;it\u00e9rations. Lancer le benchmark avec <code>-prof gc<\/code> (profiler int\u00e9gr\u00e9 \u00e0 JMH en mode garbage collection) permet de voir que pour 10 \u00e9l\u00e9ments on a quasiment aucune allocation m\u00e9moire pour une boucle for mais 192 Mo\/s d&rsquo;allocation m\u00e9moire pour un Stream.<\/p>\n<p>Par contre, pour un nombre d&rsquo;it\u00e9rations plus grand, on n&rsquo;a quasiment plus d&rsquo;allocations m\u00e9moire et la diff\u00e9rence de performance au profit d&rsquo;un Stream devient difficilement explicable. En regardant le code g\u00e9n\u00e9r\u00e9 par le JIT (via <code>-prof perfasm<\/code>) on peut voir qu&rsquo;il y a beaucoup moins d&rsquo;instructions g\u00e9n\u00e9r\u00e9es pour un <code>forEach<\/code> de Stream que pour une boucle for, entre autre \u00e0 chaque tour de boucle for on fait un appel \u00e0 <code>ArrayList.next()<\/code> qui fait lui-m\u00eame un appel \u00e0 <code>ArrayList.checkForComodification()<\/code>. Je pense qu&rsquo;en se basant sur des tableaux et pas des listes les r\u00e9sultats auraient \u00e9t\u00e9 diff\u00e9rents.<\/p>\n<h2>Benchmark 2 : somme de nombres<\/h2>\n<p>Testons maintenant avec une op\u00e9ration un peu plus complexe : on va r\u00e9aliser la somme des entiers de la liste. Comme on peut le faire de nombreuses mani\u00e8res diff\u00e9rentes avec les Stream on va en tester deux : un <code>reduce<\/code> et un <code>mapToInt<\/code> (qui transforme en IntStream) suivi d&rsquo;un <code>sum<\/code>.<\/p>\n<pre>\n    @Benchmark\n    public int testForLoop_Accumulation() {\n        int acc = 0;\n        for (Integer i : list) {\n            acc += i;\n        }\n        return acc;\n    }\n\n    @Benchmark\n    public Integer testStream_AccumulationByMap() {\n        return list.stream().mapToInt(Integer::valueOf).sum();\n    }\n\n    @Benchmark\n    public Integer testStream_AccumulationByReduce() {\n        return list.stream().reduce(0, Integer::sum);\n    }\n<\/pre>\n<p>Et voici les r\u00e9sultats :<\/p>\n<pre>\nForVsStream.testForLoop_Accumulation               10  avgt    5      12,960 \u00b1     0,809  ns\/op\nForVsStream.testForLoop_Accumulation             1000  avgt    5     749,318 \u00b1    14,473  ns\/op\nForVsStream.testForLoop_Accumulation            10000  avgt    5    6679,846 \u00b1    81,442  ns\/op\nForVsStream.testStream_AccumulationByMap           10  avgt    5      51,954 \u00b1     3,562  ns\/op\nForVsStream.testStream_AccumulationByMap         1000  avgt    5    4638,615 \u00b1   394,359  ns\/op\nForVsStream.testStream_AccumulationByMap        10000  avgt    5   52717,408 \u00b1  4893,117  ns\/op\nForVsStream.testStream_AccumulationByReduce        10  avgt    5      33,495 \u00b1     2,197  ns\/op\nForVsStream.testStream_AccumulationByReduce      1000  avgt    5    5635,545 \u00b1   476,337  ns\/op\nForVsStream.testStream_AccumulationByReduce     10000  avgt    5   43167,492 \u00b1  3646,626  ns\/op\n<\/pre>\n<p>L\u00e0 on a une diff\u00e9rence flagrante entre une boucle for et l&rsquo;utilisation d&rsquo;un Stream : avec 10000 \u00e9l\u00e9ments la boucle for est quasiment 10x plus rapide! Ce qui est int\u00e9ressant c&rsquo;est que les deux impl\u00e9mentations avec les Stream offrent des performances similaires.\nQuand on regarde les allocations m\u00e9moire, on a pour le coup \u00e9norm\u00e9ment d&rsquo;allocations m\u00e9moire pour 1000 et 10000 \u00e9l\u00e9ments pour les Stream (environ 35O  Mo\/s et 425  Mo\/s pour le mapToInt, 30% moins pour le reduce).<\/p>\n<p>Apparemment, c&rsquo;est bien la cr\u00e9ation d&rsquo;objet interm\u00e9diaire n\u00e9cessaires pour les op\u00e9rations sur les Streams qui impacte les performances.<\/p>\n<p>Le JIT Graal est cit\u00e9 comme ayant des optimisations plus pouss\u00e9es sur les Stream, lan\u00e7ons donc le benchmark avec Graal au lieu du JIT par d\u00e9faut d&rsquo;OpenJDK : C2.\nJ&rsquo;ai utilis\u00e9 GraalVM 19.3.1-java11 pour plus de simplicit\u00e9 mais on peut utiliser le JIT Graal avec OpenJDK.<\/p>\n<pre>\nForVsStream.testForLoop_Accumulation               10  avgt    5      25,960 \u00b1     1,414  ns\/op\nForVsStream.testForLoop_Accumulation             1000  avgt    5    2422,501 \u00b1   385,645  ns\/op\nForVsStream.testForLoop_Accumulation            10000  avgt    5   25197,850 \u00b1  6781,623  ns\/op\nForVsStream.testStream_AccumulationByMap           10  avgt    5      50,210 \u00b1     3,361  ns\/op\nForVsStream.testStream_AccumulationByMap         1000  avgt    5    1601,862 \u00b1    53,173  ns\/op\nForVsStream.testStream_AccumulationByMap        10000  avgt    5   15947,271 \u00b1   759,564  ns\/op\nForVsStream.testStream_AccumulationByReduce        10  avgt    5      35,362 \u00b1     8,530  ns\/op\nForVsStream.testStream_AccumulationByReduce      1000  avgt    5    4279,177 \u00b1   151,122  ns\/op\nForVsStream.testStream_AccumulationByReduce     10000  avgt    5   43256,515 \u00b1  1942,682  ns\/op\n<\/pre>\n<p>Graal semble optimiser beaucoup mieux l&rsquo;impl\u00e9mentation via mapToInt().sum() que C2, par contre les performances via une boucle for sont deux fois moins bonne.<\/p>\n<p>Comme on ne retrouve pas ces diff\u00e9rences sur les autres benchmarks (les r\u00e9sultats ne sont pas int\u00e9gr\u00e9s dans cette article mais sont tr\u00e8s proches).\nOn peut penser que c&rsquo;est ici un probl\u00e8me \u00e9ph\u00e9m\u00e8re au moment du lancement du test, j&rsquo;ai donc relanc\u00e9 le benchmark et j&rsquo;ai toujours eu le m\u00eame r\u00e9sultat! Les boucles for sont moins bien optimis\u00e9es avec Graal. J&rsquo;ai donc demand\u00e9 aux d\u00e9veloppeurs de Graal ce qu&rsquo;ils en pensent, je mettrais \u00e0 jour l&rsquo;article avec des explications si j&rsquo;en ai ;) .<\/p>\n<blockquote class=\"twitter-tweet\"><p lang=\"en\" dir=\"ltr\"><a href=\"https:\/\/twitter.com\/thomaswue?ref_src=twsrc%5Etfw\">@thomaswue<\/a> <a href=\"https:\/\/twitter.com\/shelajev?ref_src=twsrc%5Etfw\">@shelajev<\/a> I make some microbenchmarks to compare performance of for loop vs Stream. I run them with C2 and Graal and saw some differences.<br>1. Trivial for loop that performs a sum of ints is 2x &#8211; 4x slower.<br>2. Stream that uses mapToInt().sum() is 3x quicker.<br>Results \u2b07\ufe0f<\/p>\u2014 Lo\u00efc Mathieu (@loicmathieu) <a href=\"https:\/\/twitter.com\/loicmathieu\/status\/1252241111093051393?ref_src=twsrc%5Etfw\">April 20, 2020<\/a><\/blockquote>\n<a href=\"https:\/\/platform.twitter.com\/widgets.js\">https:\/\/platform.twitter.com\/widgets.js<\/a>\n<h2>Benchmark 3 : concat\u00e9nation de String<\/h2>\n<p>Finissons par un exemple de concat\u00e9nation de String, celui-ci devrait \u00eatre moins sensible au probl\u00e8me de diff\u00e9rences de cr\u00e9ation d&rsquo;objets entre une boucle for et un Stream.<\/p>\n<pre>\n    @Benchmark\n    public String testForLoop_StringBuilder() {\n        StringBuilder builder = new StringBuilder();\n        for (Integer i : list) {\n            builder.append(i.toString());\n        }\n        return builder.toString();\n    }\n\n    @Benchmark\n    public String testStream_StringBuilderByForEach() {\n        StringBuilder builder = new StringBuilder();\n        list.stream().forEach(i -&gt; builder.append(i.toString()));\n        return builder.toString();\n    }\n\n    @Benchmark\n    public String testStream_StringBuilderByJoining() {\n        return list.stream().map(i -&gt; i.toString()).collect(Collectors.joining());\n    }\n<\/pre>\n<p>Et voici les r\u00e9sultats :<\/p>\n<pre>\nForVsStream.testForLoop_StringBuilder              10  avgt    5     148,218 \u00b1    11,181  ns\/op\nForVsStream.testForLoop_StringBuilder            1000  avgt    5   19277,681 \u00b1   524,130  ns\/op\nForVsStream.testForLoop_StringBuilder           10000  avgt    5  189820,108 \u00b1 39519,566  ns\/op\nForVsStream.testStream_StringBuilderByForEach      10  avgt    5     124,379 \u00b1     4,701  ns\/op\nForVsStream.testStream_StringBuilderByForEach    1000  avgt    5   19643,228 \u00b1  1296,197  ns\/op\nForVsStream.testStream_StringBuilderByForEach   10000  avgt    5  179761,808 \u00b1 17014,818  ns\/op\nForVsStream.testStream_StringBuilderByJoining      10  avgt    5     242,916 \u00b1    27,689  ns\/op\nForVsStream.testStream_StringBuilderByJoining    1000  avgt    5   19560,014 \u00b1  3750,284  ns\/op\nForVsStream.testStream_StringBuilderByJoining   10000  avgt    5  207933,016 \u00b1 17316,623  ns\/op\n<\/pre>\n<p>Entre une boucle for et un forEach sur un Stream, les performances sont quasiment identiques. Quand on r\u00e9alise des op\u00e9rations non triviales, il n&rsquo;y a quasiment aucune diff\u00e9rence de performance ente une boucle for et un Stream !<\/p>\n<p>Quand on utilise <code>Collectors.joining()<\/code>, les performances sont l\u00e9g\u00e8rement moins bonnes mais restent assez proches pour un nombre important d&rsquo;it\u00e9rations.<\/p>\n<h2>Conclusion<\/h2>\n<p>La diff\u00e9rence de performance entre utiliser une boucle for et un Stream est quasiment n\u00e9gligeable en elle m\u00eame, ce qui change, c&rsquo;est bien la nature des op\u00e9rations qu&rsquo;on r\u00e9alise. Dans le cas des Stream, on peut facilement r\u00e9aliser beaucoup plus d&rsquo;op\u00e9rations pour la m\u00eame t\u00e2che (exemple de la somme des nombres).<\/p>\n<p>Une des forces des Stream est de faciliter la cr\u00e9ation de pipeline d&rsquo;op\u00e9rations : \u00e0 nous de faire attention et d&rsquo;\u00eatre pragmatique dans son utilisation !<\/p>\n<p>Pour finir, je tiens \u00e0 rappeler que ce sont des micro-benchmarks : bien souvent, dans un cas r\u00e9el d&rsquo;application, le pipeline d&rsquo;op\u00e9rations sera beaucoup plus grand et donc la diff\u00e9rence de performance n\u00e9gligeable. Quand on prend en compte les optimisations du JIT et la lisibilit\u00e9 du code, bien souvent, utiliser un Stream est la meilleur solution ;)<\/p>\n<p>Pour ceux qui voudraient jouer avec le benchmark, il est disponible ici : <a href=\"https:\/\/github.com\/loicmathieu\/jmh-benchmarks\/blob\/master\/src\/main\/java\/fr\/loicmathieu\/jmh\/ForVsStream.java\" rel=\"noopener noreferrer\" target=\"_blank\"><a href=\"https:\/\/github.com\/loicmathieu\/jmh-benchmarks\/blob\/master\/src\/main\/java\/fr\/loicmathieu\/jmh\/ForVsStream.java\">https:\/\/github.com\/loicmathieu\/jmh-benchmarks\/blob\/master\/src\/main\/java\/fr\/loicmathieu\/jmh\/ForVsStream.java<\/a><\/a><\/p>\n<p>Un remerciement tout sp\u00e9cial \u00e0 Logan pour sa relecture et la correction des nombreuses fautes d&rsquo;orthographe ;)<\/p>","protected":false},"excerpt":{"rendered":"<p>Cela faisait longtemps que je n&rsquo;avais pas \u00e9crit un article de blog et pourtant, pour cause de confinement, j&rsquo;ai du temps pour le faire! N&rsquo;ayant pas d&rsquo;id\u00e9e, j&rsquo;ai demand\u00e9 \u00e0 ma twitosph\u00e8re de m&rsquo;en donner, et j&rsquo;ai eu une r\u00e9ponse int\u00e9ressante : Les diff\u00e9rences de perf entre stream et for classique ? On en a parl\u00e9 y&rsquo;a longtemps, mais j&rsquo;avais fait une session de micro bench avec JMH qui montrait que les &lsquo;for&rsquo; \u00e9taient plus performants que les streams. \u2014&#8230;<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/for-vs-stream\/\">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":[178,11,159],"class_list":["post-1030","post","type-post","status-publish","format-standard","hentry","category-informatique","tag-benchmark","tag-java","tag-performance"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":1330,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/devoxx-france-2021-ledition-9-3-4\/","url_meta":{"origin":1030,"position":0},"title":"Devoxx France 2021 &#8211; l&rsquo;\u00e9dition 9 3\/4","author":"admin","date":"vendredi  1 octobre 2021","format":false,"excerpt":"Cette semaine, c'est Devoxx France. Et pour la premi\u00e8re fois depuis pas mal de temps, je sors de chez moi, et j'y vais ! Je vous \u00e9cris ces mots dans le train de retour de la deuxi\u00e8me journ\u00e9e, pas de troisi\u00e8me pour moi cette ann\u00e9e. J'ai assist\u00e9 \u00e0 quelques talks,\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":1180,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/benchmark-conversion-de-long-en-byte\/","url_meta":{"origin":1030,"position":1},"title":"Benchmark : conversion de long en byte[]","author":"admin","date":"mardi  8 d\u00e9cembre 2020","format":false,"excerpt":"J'utilise beaucoup Kafka ces derniers temps, et dans Kafka, beaucoup de choses sont des tableaux de bytes, m\u00eame les headers ! Comme j'ai de nombreux composants qui s'\u00e9changent des messages, j'ai ajout\u00e9 des headers pour aider au suivi des messages, et entre autres un header timestamp qui a comme valeur\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":1041,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/introduction-a-jmh-java-microbenchmark-harness\/","url_meta":{"origin":1030,"position":2},"title":"Introduction \u00e0 JMH &#8211; Java Microbenchmark Harness","author":"admin","date":"mercredi 29 avril 2020","format":false,"excerpt":"Dans mon pr\u00e9c\u00e9dent article For vs Stream, j'ai utilis\u00e9 JMH \u2013 The Java Microbenchmark Harness, un outil pour r\u00e9aliser des microbenchmarks de mani\u00e8re facile, et surtout, pertinente. Cet article \u00e0 pour but de vous pr\u00e9senter l'outil et son utilisation. Mais tout d'abord : c'est quoi un microbenchmark ? Microbenchmark Benchmark\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":966,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/1-an-chez-zenika\/","url_meta":{"origin":1030,"position":3},"title":"1 an chez Zenika","author":"admin","date":"mardi  3 septembre 2019","format":false,"excerpt":"Aujourd'hui est un jour sp\u00e9cial, cela fait un an que je suis arriv\u00e9 chez Zenika, apr\u00e8s 9 ans en tant qu'architecte logiciel dans la DSI d'un grand groupe de retail. Et apr\u00e8s un an, quel est donc le bilan ? Tout d'abord, Zenika m'a surpris. Lors des \u00e9changes que j'ai\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":652,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/les-nouveautes-de-java-9-pour-les-developeurs\/","url_meta":{"origin":1030,"position":4},"title":"Les nouveaut\u00e9s de java 9 pour les d\u00e9veloppeurs","author":"admin","date":"lundi 27 mars 2017","format":false,"excerpt":"Maintenant que Java 9 est Features Complete, il est temps de se pencher sur toutes les nouveaut\u00e9s que cette nouvelle version va nous apporter, \u00e0 nous, d\u00e9velopeurs utilisant java. Bien sur, tout le monde a entendu parler de la modularisation du JDK (project Jigsaw) attendu depuis tr\u00e8s longtemps. Et bien,\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"jshell the Java REPL","src":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/jshell.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1672,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/devoxx-fr-2023-improving-your-skills-with-the-debugger-par-bouke-nijuis\/","url_meta":{"origin":1030,"position":5},"title":"Devoxx FR 2023 &#8211; Improving your skills with the Debugger par Bouke Nijuis","author":"admin","date":"vendredi 14 avril 2023","format":false,"excerpt":"Deuxi\u00e8me conf\u00e9rence \u00e0 laquelle j'assiste (et derni\u00e8re pour laquelle j'ai pris des notes), \u00e7a parle de l'utilisation du debugger. On va utiliser un programme simple de type Hello World. Apr\u00e8s un rapide rappel sur les bases de l'utilisation d'un debugger avec IntelliJ on entre dans le vif du sujet, les\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":[]}],"_links":{"self":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts\/1030","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=1030"}],"version-history":[{"count":0,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts\/1030\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/media?parent=1030"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/categories?post=1030"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/tags?post=1030"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}