{"id":1201,"date":"2021-03-02T13:06:12","date_gmt":"2021-03-02T12:06:12","guid":{"rendered":"https:\/\/www.loicmathieu.fr\/wordpress\/?p=1201"},"modified":"2021-03-04T13:35:46","modified_gmt":"2021-03-04T12:35:46","slug":"introduction-a-quickperf","status":"publish","type":"post","link":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/introduction-a-quickperf\/","title":{"rendered":"Introduction to Quickperf"},"content":{"rendered":"<p>QuickPerf is a test library for Java to quickly evaluate and improve the performance of your application.<\/p>\n<p>The great interest of Quickperf lies in the fact that this is done via unit tests, which allows, after detecting and correcting a performance problem, to have non-regression tests so that it never comes back! You can then continuously evaluate the performance of your application via your continuous integration environment!<\/p>\n<p>Quickperf can be used to simply measure performance characteristics, or to assert on it via the definition of <em>expectation<\/em>.<\/p>\n<p>Quickperf requires Java 7 minimum and works with JUnit 4 or 5 and TestNG. The examples in this article are done in Java 11 via JUnit 5.<\/p>\n<p>To use Quickperf you need to add the corresponding library to your test framework, here is an example with Maven for JUnit 5.<\/p>\n<pre>    \n\n    \n        \n            org.junit\n            junit-bom\n            5.7.0\n            pom\n            import\n        \n        \n            org.quickperf\n            quick-perf-bom\n            1.0.1\n            pom\n            import\n        \n    \n \n\n  \n    \n      org.junit.jupiter\n      junit-jupiter-engine\n      test\n    \n    \n       org.junit.platform\n       junit-platform-launcher\n       test\n    \n  \n<\/pre>\n<h2>First example<\/h2>\n<p>Before going into detail about the features of Quickperf, a small example :<\/p>\n<pre>@QuickPerfTest\npublic class JvmAnnotationsJunit5Test {\n\n    @MeasureHeapAllocation\n    @Test\n    public void test_method_measuring_heap_allocation() {\n        \/\/ java.util.ArrayList: 24 bytes + Object[]: 16 + 100 x 4 = 416 =&gt; 440 bytes\n        ArrayList data = new ArrayList(100);\n    }\n\n    @ExpectNoHeapAllocation\n    @Test\n    public void should_not_allocate() {\n    }\n}<\/pre>\n<ul><li><code>@QuickPerfTest<\/code>: is used to initialize the Quickperf JUnit5 extension (optional)<\/li>\n\n<li><code>@MeasureHeapAllocation<\/code>: will measure the memory allocations made by the test<\/li>\n\n<li><code>@ExpectNoHeapAllocation<\/code>: will create an <em>expectation<\/em> so that the test should not perform memory allocation. If this is false, the test will fail (assertion failure)<\/li>\n<\/ul>\n<p>Running these tests will give you the following result:<\/p>\n<pre>[INFO] -------------------------------------------------------\n[INFO]  T E S T S\n[INFO] -------------------------------------------------------\n[INFO] Running org.quickperf.jvm.JvmAnnotationsJunit5Test\n[QUICK PERF] Measured heap allocation (test method thread): 440 bytes\n[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.203 s - in org.quickperf.jvm.JvmAnnotationsJunit5Test\n[INFO] \n[INFO] Results:\n[INFO] \n[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0\n[INFO] \n[INFO] ------------------------------------------------------------------------\n[INFO] BUILD SUCCESS\n[INFO] ------------------------------------------------------------------------\n<\/pre>\n<p>Build Success! Great!\nBy the way, you could notice Quickperf&#8217;s measurement of the memory allocation of the test <code>test_method_measuring_heap_allocation<\/code>:<\/p>\n<pre>[QUICK PERF] Measured heap allocation (test method thread): 440 bytes\n<\/pre>\n<p>Let&#8217;s now modify the code to add an <em>expectation<\/em> for the test <code>test_method_measuring_heap_allocation<\/code> so that it must allocate less than 400 bytes of memory.<\/p>\n<pre>\n@MeasureHeapAllocation\n@ExpectMaxHeapAllocation(value = 400, unit = AllocationUnit.BYTE)\n@Test\npublic void test_method_measuring_heap_allocation() {\n    \/\/ java.util.ArrayList: 24 bytes + Object[]: 16 + 100 x 4 = 416 =&gt; 440 bytes\n    ArrayList data = new ArrayList(100);\n}\n<\/pre>\n<p>Running these modified tests will give you :<\/p>\n<pre>[INFO] -------------------------------------------------------\n[INFO]  T E S T S\n[INFO] -------------------------------------------------------\n[INFO] Running org.quickperf.jvm.JvmAnnotationsJunit5Test\n[QUICK PERF] Measured heap allocation (test method thread): 440 bytes\n[ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 2.258 s &lt;&lt;&lt; FAILURE! - in org.quickperf.jvm.JvmAnnotationsJunit5Test\n[ERROR] test_method_measuring_heap_allocation  Time elapsed: 1.106 s  &lt;&lt;&lt; FAILURE!\njava.lang.AssertionError: \na performance property is not respected\n\n[PERF] Expected heap allocation (test method thread) to be less than 400 bytes but is 440 bytes.\n\n[INFO] \n[INFO] Results:\n[INFO] \n[ERROR] Failures: \n[ERROR]   JvmAnnotationsJunit5Test.test_method_measuring_heap_allocation a performance property is not respected\n\n[PERF] Expected heap allocation (test method thread) to be less than 400 bytes but is 440 bytes.\n\n[INFO] \n[ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0\n[INFO] \n[INFO] ------------------------------------------------------------------------\n[INFO] BUILD FAILURE\n[INFO] ------------------------------------------------------------------------\n<\/pre>\n<p>Build Failure :(<\/p>\n<p>But with a human readable explanation of the cause.<\/p>\n<pre>[PERF] Expected heap allocation (test method thread) to be less than 400 bytes but is 440 bytes.\n<\/pre>\n<p>One of the specificities of Quickperf is to give you as much information as possible about the reason of the failure of the test, through sentences understandable by a human being.<\/p>\n<h2>Core annotations<\/h2>\n<p>Core annotations are available within Quickperf&#8217;s main library, they offer the following features:<\/p>\n<ul><li><code>@MeasureExecutionTime<\/code> : measures the execution time of the test method.<\/li>\n\n<li><code>@ExpectMaxExecutionTime<\/code> : create an <em>expectation<\/em> that the test should not run for more than a certain amount of time.<\/li>\n<\/ul>\n<p>There are also a number of annotations to configure Quickperf, more information <a href=\"https:\/\/github.com\/quick-perf\/doc\/wiki\/core-annotations\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>.<\/p>\n<h2>JVM annotations<\/h2>\n<p>Most JVM annotations are included in the main Quickperf library except the annotations related to <a href=\"https:\/\/en.wikipedia.org\/wiki\/JDK_Flight_Recorder\" target=\"_blank\" rel=\"noopener noreferrer\">JFR &#8211; JDK Flight Recorder<\/a> which require the addition of the library <code>org.quickperf:quick-perf-jfr-annotations<\/code>.<\/p>\n<p><strong>Warning: the use of JVM annotation causes a JVM to be started for each test method.<\/strong><\/p>\n<p>JVM annotations provide the following features :<\/p>\n<ul><li>Configuration of the JVM that will run the test via <code>@HeapSize<\/code> (to configure Xmx and Xms), <code>@Xms<\/code>, <code>@Xmx<\/code>, <code>@UseGC<\/code>, <code>@EnableGcLogging<\/code> and <code>@JvmOptions<\/code>.<\/li>\n\n<li>Measurement of memory allocations via <code>@MeasureHeapAllocation<\/code>, <code>@ExpectMaxHeapAllocation<\/code> and <code>@ExpectNoHeapAllocation<\/code>. Uses the library <a href=\"https:\/\/github.com\/danielshaya\/ByteWatcher\" target=\"_blank\" rel=\"noopener\">ByteWatcher<\/a>.<\/li>\n\n<li>Measurement of the resident set size of your JVM process via <code>@MeasureRSS<\/code> and <code>@ExpectMaxRSS<\/code>.<\/li>\n\n<li>Profiling your application via JFR.<\/li>\n<\/ul>\n<p>Small zoom on the profiling of your application via JFR. The annotation <a>@ProfileJvm<\/code>code&gt;@ProfileJvm&lt;\/code<\/a> will launch a JFR record for the execution of your method that you can then open with <a href=\"https:\/\/openjdk.java.net\/projects\/jmc\/\" target=\"_blank\" rel=\"noopener noreferrer\">JMC &#8211; JDK Mission Control<\/a>. This annotation will also display some global JFR metrics in the console.<\/p>\n<pre>------------------------------------------------------------------------------\n ALLOCATION (estimations)     |   GARBAGE COLLECTION           |  THROWABLE\n Total       : 20,1 MiB       |   Total pause     : 21,434 ms  |  Exception: 0\n Inside TLAB : 16,2 MiB       |   Longest GC pause: 21,434 ms  |  Error    : 0\n Outside TLAB: 3,95 MiB       |   Young: 1                     |  Throwable: 0\n Allocation rate: 255 MiB\/s   |   Old  : 0                     |\n------------------------------------------------------------------------------\n COMPILATION                  |   CODE CACHE\n Number : 0                   |   The number of full code cache events: 0\n Longest: 0                   |   \n------------------------------------------------------------------------------\n<\/pre>\n<p>It is possible to define <em>expectations<\/em> for this profile via the annotation <a>@ExpectNoJvmIssue<\/code>code&gt;@ExpectNoJvmIssue&lt;\/code<\/a> which will be based on the <a href=\"http:\/\/hirt.se\/blog\/?p=920\" target=\"_blank\" rel=\"noopener noreferrer\">JMC rules<\/a> to fail the test.<\/p>\n<pre>Rule: Primitive To Object Conversion\nSeverity: INFO\nScore: 73\nMessage: 78 % of the total allocation (15,1 MiB) is caused by conversion from primitive \ntypes to object types.\n\nThe most common object type that primitives are converted into is \n'java.lang.Integer', which causes 15,1 MiB to be allocated. The most common \ncall site is 'org.quickperf.jvm.IntegerAccumulator.accumulateInteger(int):26'.\n\n[...]\n<\/pre>\n<p>More information on JVM annotations <a href=\"https:\/\/github.com\/quick-perf\/doc\/wiki\/JVM-annotations\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a><\/p>\n<h2>SQL annotations<\/h2>\n<p>To use SQL annotations, you need to add the library <code>org.quickperf:quick-perf-sql-annotations<\/code> (unless you use Spring which has dedicated support). Depending on your application, you then need to configure its DataSource to add a proxy that will allow Quickperf to trace SQL queries. More information about this in the next section.<\/p>\n<p>Quickperf has a lot of annotations to check the execution of SQL queries, and to detect the most common problems: duplicate queries, n+1 select, batch, &#8230;<\/p>\n<p>Here are some of the most used annotations:<\/p>\n<ul><li><code>@ExpectJdbcQueryExecution<\/code> and <code>@ExpectMaxQueryExecutionTime<\/code>: <em>expectation<\/em> as for the execution time of a SQL query, the first one expect the exact time, the second one will fail if the measured time is greater (most SQL annotations come in pairs according to this same scheme).<\/li>\n\n<li><code>@ExpectSelectedColumn<\/code> etand<code>@ExpectMaxSelectedColumn<\/code> : <em>expectation<\/em> as to the number of selected columns<\/li>\n\n<li><code>@ExpectSelect<\/code> and <code>@ExpectMaxSelect<\/code> : <em>expectation<\/em> as to the number of selects generated\/li&gt;\n    <\/li>\n<li><code>@ExpectJdbcBatching<\/code> : <em>expectation<\/em> as to the usage of JDBC batching<\/li>\n<\/ul>\n<p>Small zoom on a particular annotation : <a>@DisableSameSelectTypesWithDifferentParamValues<\/code>code&gt;@DisableSameSelectTypesWithDifferentParamValues&lt;\/code<\/a>, this one allows to detect problems with <strong>n+1 select<\/strong> with JPA \/ Hibernate..<\/p>\n<p>This well known problem happens when two entities have a parent-child relationship, and loading the parent entity involves a select query to load it, plus n select to load its children. It is a well-known anti-pattern that is usually solved by performing a JPA <strong>JOIN FETCH<\/strong>.<\/p>\n<p>Quickperf can detect this with the annotation <a>@DisableSameSelectTypesWithDifferentParamValues<\/code>code&gt;@DisableSameSelectTypesWithDifferentParamValues&lt;\/code<\/a> which will cause your test to fail if several identical selects are executed with different parameters. And if it detects the presence of Hibernate, Quickperf will even give you advice on how to solve the problem!<\/p>\n<p>Let&#8217;s imagine the following <code>Player<\/code> and <code>Team<\/code> entities:<\/p>\n<pre>@Entity\npublic class Player implements Serializable {\n\n    @Id\n    @GeneratedValue(strategy = GenerationType.SEQUENCE)\n    private Long id;\n\n    private String firstName;\n\n    private String lastName;\n\n    @ManyToOne(targetEntity = Team.class)\n    @JoinColumn(name = \"team_id\")\n    private Team team;\n\n    \/\/ getter and setters ...\n}\n\n@Entity\npublic class Team implements Serializable {\n\n    @Id\n    @GeneratedValue(strategy = GenerationType.SEQUENCE)\n    private Long id;\n\n    private String name;\n\n   \/\/ getter and setters ...\n}\n<\/pre>\n<p>And the following test:<\/p>\n<pre>\n@DisableSameSelectTypesWithDifferentParamValues\n@Test\npublic void should_find_all_players() {\n    TypedQuery fromPlayer  = entityManager.createQuery(\"FROM Player\", Player.class);\n    List players = fromPlayer.getResultList();\n    assertThat(players).hasSize(2);\n}\n<\/pre>\n<p>Loading the class <code>Player<\/code> will result in n+1 SQL queries which will be detected by Quickperf which will then give you the following error message suggesting a problem with n+1 select and possible solutions :<\/p>\n<pre>ERROR] Failures: \n[ERROR]   HibernateJUnit5Test.should_find_all_players a performance property is not respected\n\n[PERF] Same SELECT types with different parameter values\n\n\ud83d\udca3 You may have even more select statements with production data.\nBe careful with the cost of JDBC server roundtrips: https:\/\/blog.jooq.org\/2017\/12\/18\/the-cost-of-jdbc-server-roundtrips\/\n\n\ud83d\udca1 Perhaps you are facing an N+1 select issue\n    * With Hibernate, you may fix it by using JOIN FETCH\n                                           or LEFT JOIN FETCH\n                                           or FetchType.LAZY\n                                           or ...\n      Some examples: https:\/\/stackoverflow.com\/questions\/32453989\/what-is-the-solution-for-the-n1-issue-in-jpa-and-hibernate\";\n                     https:\/\/stackoverflow.com\/questions\/52850442\/how-to-get-rid-of-n1-with-jpa-criteria-api-in-hibernate\/52945771?stw=2#52945771\n                     https:\/\/thoughts-on-java.org\/jpa-21-entity-graph-part-1-named-entity\/\n\n[...]\n<\/pre>\n<h2>Frameworks integration<\/h2>\n<p>As mentioned in the previous section, Quickperf requires a proxy from your DataSource to be able to detect SQL problems. Depending on the frameworks you use, you will need to set up this proxy.<\/p>\n<p>This consists of a few lines of code that will define a wrapper on top of your DataSource:<\/p>\n<pre>\npublic DataSource wrapDatasource(DataSource dataSource){\n    ProxyDataSource proxyDataSource = QuickPerfSqlDataSourceBuilder.aDataSourceBuilder()\n            .buildProxy(dataSource);\n    return proxyDataSource;\n}\n<\/pre>\n<p>The repository <a href=\"https:\/\/github.com\/quick-perf\/quickperf-examples\/\" target=\"_blank\" rel=\"noopener\">quickperf-examples<\/a> contains many examples of implementation of this proxy for the most common frameworks (Spring, Hibernate, Micronaut, &#8230;).<\/p>\n<p>If you use Spring, the configuration is simplified, you don&#8217;t need to add the library <code>org.quickperf:quick-perf-sql-annotations<\/code>, instead you have to add a dedicated library and everything is done automatically. For example, for Spring Boot 2, you have to add the starter <code>quick-perf-springboot2-sql-starter<\/code>.<\/p>\n<pre>\n\n    org.quickperf\n    quick-perf-springboot2-sql-starter\n    test\n\n<\/pre>\n<p>More information about SQL annotation support with Spring <a href=\"https:\/\/github.com\/quick-perf\/doc\/wiki\/Spring#sql-annotations\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<p>Quickperf will not only detect performance problems, it will also give advice on how to solve them by listing the most common causes. It will detect the frameworks used by your application (Hibernate, Spring Boot, &#8230;) and customize the advice given accordingly.<\/p>\n<p>According to the detected frameworks, Quickperf will also suggest solutions to the problems of using Quickperf itself.<\/p>\n<p>For example, in case of n+1 problem with an application using Spring Data JPA, Quickperf will give you a help on how to fix it specifically with Spring Data JPA (the tips for Hibernate have been removed from the example to improve its readability).<\/p>\n<pre>[PERF] You may think that  select statement was sent to the database\n       But there are in fact ...\n\n\ud83d\udca3 You may have even more select statements with production data.\nBe careful with the cost of JDBC roundtrips: https:\/\/blog.jooq.org\/2017\/12\/18\/the-cost-of-jdbc-server-roundtrips\/\n\n\ud83d\udca1 Perhaps you are facing an N+1 select issue\n    * With Hibernate [...]\n\n    * With Spring Data JPA, you may fix it by adding @EntityGraph(attributePaths = { \"...\" })\n      on repository method: https:\/\/docs.spring.io\/spring-data\/jpa\/docs\/current\/reference\/html\/#jpa.entity-graph\n<\/pre>\n<h2>Conclusion<\/h2>\n<p>Quickperf is a tool that allows you to add continuous performance non-regression thanks to its integration via test frameworks (JUnit, TestNG).<\/p>\n<p>It allows you to detect the most common performance problems in Java (memory allocation, querying, &#8230;), to profile your application via a test, and more. Once these problems have been detected and corrected thanks to the advice it provides, your test will become the guarantee of non-regression in the performance of your application.<\/p>\n<p>Quickperf was successfully used to measure Maven&#8217;s memory consumption improvements between versions 3.6.1 and 3.6.2. As a result, a bench has been created to continuously monitor Maven&#8217;s memory allocations. This is a good example of how Quickperf was used on a complex project and how much it saved.<\/p>","protected":false},"excerpt":{"rendered":"<p>QuickPerf is a test library for Java to quickly evaluate and improve the performance of your application. The great interest of Quickperf lies in the fact that this is done via unit tests, which allows, after detecting and correcting a performance problem, to have non-regression tests so that it never comes back! You can then continuously evaluate the performance of your application via your continuous integration environment! Quickperf can be used to simply measure performance characteristics, or to assert on&#8230;<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/introduction-a-quickperf\/\"> 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":[11,159,190],"class_list":["post-1201","post","type-post","status-publish","format-standard","hentry","category-informatique","tag-java","tag-performance","tag-quickperf"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"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":1201,"position":0},"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":1041,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/introduction-a-jmh-java-microbenchmark-harness\/","url_meta":{"origin":1201,"position":1},"title":"(Fran\u00e7ais) Introduction \u00e0 JMH &#8211; Java Microbenchmark Harness","author":"admin","date":"Wednesday April 29th, 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":1153,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/profiler-une-image-native-graalvm-avec-perf\/","url_meta":{"origin":1201,"position":2},"title":"Profiling a GraalVM native image with perf","author":"admin","date":"Monday November 16th, 2020","format":false,"excerpt":"The GraalVM native-image tool allows you to generate a native executable (or native image) from your Java application. This native executable will start very quickly and have a much smaller memory footprint than a traditional Java application; at the cost of reduced peak performance and a relatively high packaging build\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\/flamegraph-2.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/flamegraph-2.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/flamegraph-2.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/flamegraph-2.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1090,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/quarkus-jlink-et-application-class-data-sharing-appcds\/","url_meta":{"origin":1201,"position":3},"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":1375,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/java-18-quoi-de-neuf\/","url_meta":{"origin":1201,"position":4},"title":"Java 18 : what&#8217;s new ?","author":"admin","date":"Tuesday January  4th, 2022","format":false,"excerpt":"Now that Java 18 is features complete (Rampdown Phase One 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":1068,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/j-ai-teste-java-google-cloud-functions-aplha\/","url_meta":{"origin":1201,"position":5},"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":[]}],"_links":{"self":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts\/1201","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=1201"}],"version-history":[{"count":0,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts\/1201\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/media?parent=1201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/categories?post=1201"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/tags?post=1201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}