{"id":1920,"date":"2025-03-12T13:26:40","date_gmt":"2025-03-12T12:26:40","guid":{"rendered":"https:\/\/www.loicmathieu.fr\/wordpress\/?p=1920"},"modified":"2025-03-12T13:26:40","modified_gmt":"2025-03-12T12:26:40","slug":"benchmark-concatener-des-listes","status":"publish","type":"post","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/benchmark-concatener-des-listes\/","title":{"rendered":"Benchmark : concat\u00e9ner des listes"},"content":{"rendered":"<p>Il y a peu, je suis tomb\u00e9 sur ce bout de code qui concat\u00e8ne deux listes en utilisant la classe utilitaire <code>Lists<\/code> de Guava puis l&rsquo;API Stream :<\/p>\n<pre>\nLists.newArrayList(collectionOriginal,collectionValue)\n        .stream()\n        .flatMap(Collection::stream)\n        .toList();\n<\/pre>\n<p>Comme ce bout de code est dans le chemin critique de l&rsquo;application et donc appel\u00e9 tr\u00e8s fr\u00e9quemment, je me suis demand\u00e9 si c&rsquo;\u00e9tait la meilleure mani\u00e8re de concat\u00e9ner deux listes.<\/p>\n<p>On peut concat\u00e9ner deux listes de beaucoup de mani\u00e8res diff\u00e9rentes :<\/p>\n<ul><li>Avec le code ci-dessus<\/li>\n\n<li>Avec <code>Stream.concat()<\/code><\/li>\n\n<li>Avec <code>Stream.of()<\/code><\/li>\n\n<li>Avec <code>ListUtils<\/code> d&rsquo;Apache Commons Collection<\/li>\n\n<li>Avec <code>ArrayList.addAll()<\/code><\/li>\n<\/ul>\n<p>Il y a certainement d&rsquo;autre mani\u00e8re, mais je voulais d\u00e9j\u00e0 comparer ces cinq l\u00e0 !<\/p>\n<p>Pour comparer ces cinq solutions, rien de mieux que JMH &#8211; <a href=\"https:\/\/github.com\/openjdk\/jmh\" target=\"_blank\" rel=\"noopener noreferrer\">The Java Microbenchmark Harness<\/a>. Cet outil nous permet d\u2019\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\u00e9rer \u00e0 cet article : <a href=\"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/introduction-a-jmh-java-microbenchmark-harness\/\" target=\"_blank\" rel=\"noopener noreferrer\">INTRODUCTION \u00c0 JMH \u2013 JAVA MICROBENCHMARK HARNESS<\/a>.<\/p>\n<h2>Le benchmark<\/h2>\n<p>Pour pouvoir comparer sur plusieurs tailles de liste, j&rsquo;utilise <a>@Param<\/code>code&gt;@Param&lt;\/code<\/a> pour param\u00e9triser la taille des listes \u00e0 concat\u00e9ner. Voici le setup que j&rsquo;ai utilis\u00e9 :<\/p>\n<pre>\n@Param({\"10\", \"1000\", \"10000\"})\nint size;\n\nList list1;\nList list2;\n\n@Setup\npublic void setup() {\n    list1 = new ArrayList(size);\n    list2 = new ArrayList(size);\n    for (int i = 0; i <\/pre>\n<p>Voici ensuite l&rsquo;impl\u00e9mentation des cinq benchmarks<\/p>\n<pre>\n@Benchmark\npublic List concatWithStreamConcat() {\n    return Stream.concat(list1.stream(), list2.stream())\n            .toList();\n}\n\n@Benchmark\npublic List concatWithStreamOf() {\n    return Stream.of(list1, list2)\n            .flatMap(List::stream)\n            .toList();\n}\n\n@Benchmark\npublic List concatWithGuava() {\n    return Lists.newArrayList(list1, list2)\n            .stream()\n            .flatMap(Collection::stream)\n            .toList();\n}\n\n@Benchmark\npublic List concatWithCommonsCollection() {\n    return ListUtils.union(list1, list2);\n}\n\n@Benchmark\npublic List concatWithNewArrayList() {\n    List newList = new ArrayList(list1.size() + list2.size());\n    newList.addAll(list1);\n    newList.addAll(list2);\n    return newList;\n}\n<\/pre>\n<h2>Les r\u00e9sultats<\/h2>\n<p>Tous les tests ont \u00e9t\u00e9 ex\u00e9cut\u00e9s sur mon laptop : Intel(R) Core(TM) i7-1260P 8 coeurs (16 avec hyperthreading) \u2013 Ubuntu 24.10.<\/p>\n<p>La version de Java utilis\u00e9 est openjdk version \u00ab\u00a021.0.5\u00a0\u00bb 2024-10-15 LTS.<\/p>\n<pre>\n Benchmark                               (size)  Mode  Cnt       Score        Error  Units\n ConcatList.concatWithCommonsCollection      10  avgt    5      57,706 \u00b1     27,376  ns\/op\n ConcatList.concatWithCommonsCollection    1000  avgt    5    1631,110 \u00b1    472,323  ns\/op\n ConcatList.concatWithCommonsCollection   10000  avgt    5   15434,192 \u00b1   2164,191  ns\/op\n ConcatList.concatWithGuava                  10  avgt    5     225,249 \u00b1     83,069  ns\/op\n ConcatList.concatWithGuava                1000  avgt    5    7967,360 \u00b1   8693,234  ns\/op\n ConcatList.concatWithGuava               10000  avgt    5  108601,706 \u00b1 104439,847  ns\/op\n ConcatList.concatWithNewArrayList           10  avgt    5      54,327 \u00b1     10,894  ns\/op\n ConcatList.concatWithNewArrayList         1000  avgt    5    1515,667 \u00b1    595,135  ns\/op\n ConcatList.concatWithNewArrayList        10000  avgt    5   14827,026 \u00b1   1253,715  ns\/op\n ConcatList.concatWithStreamConcat           10  avgt    5     111,837 \u00b1     26,451  ns\/op\n ConcatList.concatWithStreamConcat         1000  avgt    5    7104,415 \u00b1   4030,866  ns\/op\n ConcatList.concatWithStreamConcat        10000  avgt    5   57587,144 \u00b1  13994,551  ns\/op\n ConcatList.concatWithStreamOf               10  avgt    5     157,634 \u00b1     55,757  ns\/op\n ConcatList.concatWithStreamOf             1000  avgt    5    5915,797 \u00b1   1692,437  ns\/op\n ConcatList.concatWithStreamOf            10000  avgt    5   58156,102 \u00b1   1655,090  ns\/op\n<\/pre>\n<p>Ce qui saute directement aux yeux, c&rsquo;est que la version utilis\u00e9e aujourd&rsquo;hui est la pire :(.\nSi on la laisse de c\u00f4t\u00e9, on constate que <strong>concatWithStreamOf<\/strong> et <strong>concatWithStreamConcat<\/strong> ont quasiment la m\u00eame performance, ainsi que <strong>concatWithNewArrayList<\/strong> et <strong>concatWithCommonsCollection<\/strong>. En regardant le code de <code>ListUtils.union(list1, list2)<\/code> on s\u2019aper\u00e7oit qu&rsquo;il fait exactement ce qui est fait dans <strong>concatWithNewArrayList<\/strong>.<\/p>\n<h2>Analyse plus pouss\u00e9e<\/h2>\n<p>Pour aller plus loin dans l&rsquo;analyse, relan\u00e7ons le benchmark avec le profiler GC int\u00e9gr\u00e9 \u00e0 JMH via l&rsquo;option ligne de commande <code>-prof gc<\/code>, c&rsquo;est souvent un bon d\u00e9but ;). Ce qui m\u2019int\u00e9resse tout particuli\u00e8rement, c&rsquo;est le d\u00e9bit d&rsquo;allocation m\u00e9moire (allocation rate).<\/p>\n<pre>\nConcatList.concatWithCommonsCollection:\u00b7gc.alloc.rate.norm                   10  avgt    5     232,012 \u00b1     0,002    B\/op\nConcatList.concatWithCommonsCollection:\u00b7gc.alloc.rate.norm                 1000  avgt    5   16072,479 \u00b1     0,036    B\/op\nConcatList.concatWithCommonsCollection:\u00b7gc.alloc.rate.norm                10000  avgt    5  160077,107 \u00b1     0,434    B\/op\nConcatList.concatWithGuava:\u00b7gc.alloc.rate.norm                               10  avgt    5     888,058 \u00b1     0,009    B\/op\nConcatList.concatWithGuava:\u00b7gc.alloc.rate.norm                             1000  avgt    5   16969,104 \u00b1     0,221    B\/op\nConcatList.concatWithGuava:\u00b7gc.alloc.rate.norm                            10000  avgt    5  212148,835 \u00b1     2,822    B\/op\nConcatList.concatWithNewArrayList:\u00b7gc.alloc.rate.norm                        10  avgt    5     232,011 \u00b1     0,003    B\/op\nConcatList.concatWithNewArrayList:\u00b7gc.alloc.rate.norm                      1000  avgt    5   16072,511 \u00b1     0,040    B\/op\nConcatList.concatWithNewArrayList:\u00b7gc.alloc.rate.norm                     10000  avgt    5  160076,834 \u00b1     0,366    B\/op\nConcatList.concatWithStreamConcat:\u00b7gc.alloc.rate.norm                        10  avgt    5     424,023 \u00b1     0,006    B\/op\nConcatList.concatWithStreamConcat:\u00b7gc.alloc.rate.norm                      1000  avgt    5    8344,716 \u00b1     0,173    B\/op\nConcatList.concatWithStreamConcat:\u00b7gc.alloc.rate.norm                     10000  avgt    5   80350,980 \u00b1     1,306    B\/op\nConcatList.concatWithStreamOf:\u00b7gc.alloc.rate.norm                            10  avgt    5     824,037 \u00b1     0,007    B\/op\nConcatList.concatWithStreamOf:\u00b7gc.alloc.rate.norm                          1000  avgt    5   16905,076 \u00b1     0,208    B\/op\nConcatList.concatWithStreamOf:\u00b7gc.alloc.rate.norm                         10000  avgt    5  212083,533 \u00b1     2,497    B\/op\n<\/pre>\n<p>Ici, on va s\u2019int\u00e9resse \u00e0 la valeur de <code>gc.alloc.rate.norm<\/code> c&rsquo;est le d\u00e9bit d&rsquo;allocation m\u00e9moire normalis\u00e9 par op\u00e9ration, et on voit tout de suite une grande diff\u00e9rence. Si on prend comme r\u00e9f\u00e9rence <b>ConcatList.concatWithNewArrayList<\/b> :<\/p>\n<ul><li><strong>concatWithCommonsCollection<\/strong> : allocation identique.<\/li>\n\n<li><strong>concatWithGuava<\/strong> : 4x plus d&rsquo;allocation.<\/li>\n\n<li><strong>concatWithStreamConcat<\/strong> : 2x plus d&rsquo;allocation.<\/li>\n\n<li><strong>concatWithStreamOf<\/strong> : 4x plus d&rsquo;allocation.<\/li>\n<\/ul>\n<p>Cela explique une partie des diff\u00e9rences de performance, mais pas tout.<\/p>\n<p>Relan\u00e7ons le test avec le profiler <strong>stack<\/strong> qui est un profiler simple et na\u00eff int\u00e9gr\u00e9 \u00e0 JMH.<\/p>\n<pre>\n# Benchmark: fr.loicmathieu.jmh.ConcatList.concatWithCommonsCollection\n# Parameters: (size = 10)\n\n....[Thread state: RUNNABLE]........................................................................\n 33,3%  50,0% $lt;stack is empty, everything is filtered?&gt;\n 31,6%  47,4% fr.loicmathieu.jmh.ConcatList.concatWithCommonsCollection\n  1,5%   2,3% fr.loicmathieu.jmh.jmh_generated.ConcatList_concatWithCommonsCollection_jmhTest.concatWithCommonsCollection_avgt_jmhStub\n  0,1%   0,1% java.util.ArrayList.\n  0,1%   0,1% java.util.Arrays.copyOf\n  0,0%   0,0% org.apache.commons.collections4.ListUtils.union\n  0,0%   0,0% java.lang.invoke.MethodHandle.maybeCustomize\n\n# Benchmark: fr.loicmathieu.jmh.ConcatList.concatWithGuava\n# Parameters: (size = 10)\n\n....[Thread state: RUNNABLE]........................................................................\n 33,3%  50,0% $lt;stack is empty, everything is filtered?&gt;\n 19,2%  28,8% java.util.stream.SpinedBuffer.ensureCapacity\n  5,3%   8,0% java.util.stream.AbstractPipeline.wrapSink\n  3,4%   5,1% java.util.stream.ReferencePipeline.toArray\n  3,2%   4,8% java.util.stream.SpinedBuffer.copyInto\n  2,1%   3,1% fr.loicmathieu.jmh.jmh_generated.ConcatList_concatWithGuava_jmhTest.concatWithGuava_avgt_jmhStub\n  0,1%   0,1% java.util.stream.StreamSupport.stream\n  0,0%   0,0% java.util.stream.ReferencePipeline.lambda$toArray$0\n  0,0%   0,0% java.util.ArrayList.spliterator\n  0,0%   0,0% java.util.stream.SpinedBuffer.inflateSpine\n\n# Benchmark: fr.loicmathieu.jmh.ConcatList.concatWithNewArrayList\n# Parameters: (size = 10)\n\n....[Thread state: RUNNABLE]........................................................................\n 33,3%  50,0% $lt;stack is empty, everything is filtered?&gt;\n 24,4%  36,6% java.util.ArrayList.addAll\n  8,7%  13,1% fr.loicmathieu.jmh.jmh_generated.ConcatList_concatWithNewArrayList_jmhTest.concatWithNewArrayList_avgt_jmhStub\n  0,1%   0,2% java.util.Arrays.copyOf\n  0,0%   0,1% java.util.ArrayList.\n  0,0%   0,0% fr.loicmathieu.jmh.ConcatList.concatWithNewArrayList\n\n# Benchmark: fr.loicmathieu.jmh.ConcatList.concatWithStreamConcat\n# Parameters: (size = 10)\n\n....[Thread state: RUNNABLE]........................................................................\n 33,3%  50,0% $lt;stack is empty, everything is filtered?&gt;\n 22,5%  33,8% java.util.ArrayList$ArrayListSpliterator.forEachRemaining\n  5,8%   8,7% fr.loicmathieu.jmh.ConcatList.concatWithStreamConcat\n  3,7%   5,6% java.util.stream.ReferencePipeline.toArray\n  1,1%   1,7% fr.loicmathieu.jmh.jmh_generated.ConcatList_concatWithStreamConcat_jmhTest.concatWithStreamConcat_avgt_jmhStub\n  0,0%   0,1% java.util.ImmutableCollections.listFromTrustedArrayNullsAllowed\n  0,0%   0,1% java.util.stream.ReferencePipeline.lambda$toArray$0\n  0,0%   0,1% java.util.stream.StreamSupport.stream\n  0,0%   0,0% java.util.ArrayList.spliterator\n\n# Benchmark: fr.loicmathieu.jmh.ConcatList.concatWithStreamOf\n# Parameters: (size = 10)\n\n....[Thread state: RUNNABLE]........................................................................\n 33,3%  50,0% $lt;stack is empty, everything is filtered?&gt;\n 16,9%  25,4% java.util.ArrayList$ArrayListSpliterator.forEachRemaining\n  4,5%   6,8% java.util.stream.SpinedBuffer.copyInto\n  4,5%   6,7% java.util.stream.AbstractPipeline.wrapSink\n  3,4%   5,2% java.util.stream.SpinedBuffer.ensureCapacity\n  3,4%   5,0% fr.loicmathieu.jmh.jmh_generated.ConcatList_concatWithStreamOf_jmhTest.concatWithStreamOf_avgt_jmhStub\n  0,3%   0,5% java.util.stream.ReferencePipeline.toArray\n  0,1%   0,2% java.util.stream.ReferencePipeline$Head.forEach\n  0,0%   0,0% java.util.ArrayList.spliterator\n  0,0%   0,0% java.util.stream.SpinedBuffer.inflateSpine\n<\/pre>\n<p><strong>concatWithCommonsCollection<\/strong> et <strong>concatWithNewArrayList<\/strong> utilisent tous les deux <code>java.util.Arrays.copyOf<\/code>, cette m\u00e9thode est annot\u00e9e par <a>@IntrinsicCandidate<\/code>code&gt;@IntrinsicCandidate&lt;\/code<\/a> ce qui veut dire qu&rsquo;il y a un <em>intrinsic<\/em> qui permet de l&rsquo;optimiser directement au sein de la JVM. \u00c0 ma connaissance, m\u00eame si l&rsquo;annotation contient <strong>Candidate<\/strong> dans le nom, au sein de la JVM OpenJDK d&rsquo;Oracle il y a toujours au moins un intrinsic pour une des architectures support\u00e9es (ce qui peut ne pas \u00eatre le cas pour d&rsquo;autres fournisseurs de JVM). Cet intrinsic permet une copie efficiente en m\u00e9moire des tableaux des \u00e9l\u00e9ments de la liste sans n\u00e9cessiter de parcours de la liste et copie un \u00e0 un des \u00e9l\u00e9ments.<\/p>\n<p><strong>concatWithStreamConcat<\/strong> et <strong>concatWithStreamOf<\/strong> tous les deux parcourent tous les \u00e9l\u00e9ments de la liste via <code>java.util.ArrayList$ArrayListSpliterator.forEachRemaining<\/code> ce qui est moins efficace.<\/p>\n<p><strong>concatWithGuava<\/strong> parcours aussi tous les \u00e9l\u00e9ments de la liste, mais en plus va cr\u00e9er une liste avec les deux premi\u00e8res listes ce qui va doubler le nombre de fois o\u00f9 les \u00e9l\u00e9ments sont copi\u00e9s !<\/p>\n<h2>Conclusion<\/h2>\n<p>Le code le plus simple est souvent le plus performant m\u00eame s&rsquo;il n&rsquo;est pas forc\u00e9ment le plus \u00e9l\u00e9gant.<\/p>\n<p>La JVM contient de nombreux intrinsics qui permettent des op\u00e9rations de copie en m\u00e9moire de tableaux, ceux-ci sont primordiaux quand on travaille avec de grande liste de donn\u00e9es.<\/p>\n<p>Bien s\u00fbr, cette optimisation n&rsquo;a du sens que si le code appel\u00e9 est dans le chemin critique de l\u2019application, ici, la concat\u00e9nation est potentiellement r\u00e9alis\u00e9e des milliers de fois par seconde dans <a href=\"https:\/\/www.kestra.io\" rel=\"noopener\" target=\"_blank\">Kestra<\/a>, c&rsquo;est donc important qu&rsquo;elle soit r\u00e9alis\u00e9e de la mani\u00e8re la plus performante.<\/p>\n<p>Pour rappel, cet article contient des nombres qui ne sont que \u00e7a, des nombres, ils peuvent \u00eatre tr\u00e8s diff\u00e9rents d&rsquo;un contexte \u00e0 l&rsquo;autre. Il est toujours mieux de r\u00e9aliser vous-m\u00eame vos benchmarks, dans votre contexte puis de les valider dans un environnement r\u00e9el pour en d\u00e9duire la pertinence.<\/p>\n<p>Pour les curieux, voici la PR dans le repo <a href=\"https:\/\/www.kestra.io\" rel=\"noopener\" target=\"_blank\">Kestra<\/a>: <a href=\"https:\/\/github.com\/kestra-io\/kestra\/pull\/7160\" rel=\"noopener\" target=\"_blank\"><a href=\"https:\/\/github.com\/kestra-io\/kestra\/pull\/7160\">https:\/\/github.com\/kestra-io\/kestra\/pull\/7160<\/a><\/a> et voici le benchmark complet : <a href=\"https:\/\/github.com\/loicmathieu\/jmh-benchmarks\/blob\/master\/src\/main\/java\/fr\/loicmathieu\/jmh\/ConcatList.java\" title=\"ConcatList.java\" rel=\"noopener\" target=\"_blank\">ConcatList.java<\/a>.\n<\/p>","protected":false},"excerpt":{"rendered":"<p>Il y a peu, je suis tomb\u00e9 sur ce bout de code qui concat\u00e8ne deux listes en utilisant la classe utilitaire Lists de Guava puis l&rsquo;API Stream : Lists.newArrayList(collectionOriginal,collectionValue) .stream() .flatMap(Collection::stream) .toList(); Comme ce bout de code est dans le chemin critique de l&rsquo;application et donc appel\u00e9 tr\u00e8s fr\u00e9quemment, je me suis demand\u00e9 si c&rsquo;\u00e9tait la meilleure mani\u00e8re de concat\u00e9ner deux listes. On peut concat\u00e9ner deux listes de beaucoup de mani\u00e8res diff\u00e9rentes : Avec le code ci-dessus Avec Stream.concat() Avec&#8230;<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/benchmark-concatener-des-listes\/\">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,188,189,159],"class_list":["post-1920","post","type-post","status-publish","format-standard","hentry","category-informatique","tag-benchmark","tag-java","tag-jmh","tag-micro-benchmark","tag-performance"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":1030,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/for-vs-stream\/","url_meta":{"origin":1920,"position":0},"title":"For vs Stream","author":"admin","date":"mardi 21 avril 2020","format":false,"excerpt":"Cela faisait longtemps que je n'avais pas \u00e9crit un article de blog et pourtant, pour cause de confinement, j'ai du temps pour le faire! N'ayant pas d'id\u00e9e, j'ai demand\u00e9 \u00e0 ma twitosph\u00e8re de m'en donner, et j'ai eu une r\u00e9ponse int\u00e9ressante : Les diff\u00e9rences de perf entre stream et for\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":739,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/les-optimisations-de-performances-de-java-9\/","url_meta":{"origin":1920,"position":1},"title":"Les optimisations de performances de Java 9","author":"admin","date":"vendredi 26 janvier 2018","format":false,"excerpt":"Dans un pr\u00e9c\u00e9dent article sur Java 9, j'avais parcouru les principales nouveaut\u00e9s \u00e0 destination des d\u00e9veloppeurs : http:\/\/www.loicmathieu.fr\/wordpress\/informatique\/les-nouveautes-de-java-9-pour-les-developeurs. Je vais ici parcourir les principales nouveaut\u00e9s ax\u00e9es sur la performance Je vais encore reprendre les principales JEP : JEP 143: Improve Contended Locking Optimisation des monitors Java (optimisation des locks) 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":"","width":0,"height":0},"classes":[]},{"id":1330,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/devoxx-france-2021-ledition-9-3-4\/","url_meta":{"origin":1920,"position":2},"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":1041,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/introduction-a-jmh-java-microbenchmark-harness\/","url_meta":{"origin":1920,"position":3},"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":1180,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/benchmark-conversion-de-long-en-byte\/","url_meta":{"origin":1920,"position":4},"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":966,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/1-an-chez-zenika\/","url_meta":{"origin":1920,"position":5},"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":[]}],"_links":{"self":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts\/1920","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=1920"}],"version-history":[{"count":10,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts\/1920\/revisions"}],"predecessor-version":[{"id":1932,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts\/1920\/revisions\/1932"}],"wp:attachment":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/media?parent=1920"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/categories?post=1920"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/tags?post=1920"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}