From d54127d7c6b1b493f2edcf61c28bc70b2956a2bf Mon Sep 17 00:00:00 2001
From: Denis Stepanov <denis.s.stepanov@oracle.com>
Date: Fri, 16 Feb 2024 10:49:29 +0100
Subject: [PATCH] Add startup benchmark (#762)

---
 benchmarks/build.gradle                       |   5 +-
 .../io/micronaut/serde/StartupBenchmark.java  | 111 ++++++++++++++++++
 .../io/micronaut/serde/data/SimpleBean.java   |  26 ++++
 3 files changed, 141 insertions(+), 1 deletion(-)
 create mode 100644 benchmarks/src/jmh/java/io/micronaut/serde/StartupBenchmark.java
 create mode 100644 benchmarks/src/jmh/java/io/micronaut/serde/data/SimpleBean.java

diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle
index a9359d699..05ed4d547 100644
--- a/benchmarks/build.gradle
+++ b/benchmarks/build.gradle
@@ -22,7 +22,10 @@ dependencies {
 }
 
 jmh {
-    includes = ["io.micronaut.serde.JacksonBenchmark"]
+    includes = ["io.micronaut.serde.StartupBenchmark"]
+    fork = 10
+    iterations = 1
+    warmupIterations = 0
     duplicateClassesStrategy = DuplicatesStrategy.EXCLUDE
 }
 
diff --git a/benchmarks/src/jmh/java/io/micronaut/serde/StartupBenchmark.java b/benchmarks/src/jmh/java/io/micronaut/serde/StartupBenchmark.java
new file mode 100644
index 000000000..b7219a6f5
--- /dev/null
+++ b/benchmarks/src/jmh/java/io/micronaut/serde/StartupBenchmark.java
@@ -0,0 +1,111 @@
+package io.micronaut.serde;
+
+import io.micronaut.context.ApplicationContext;
+import io.micronaut.core.type.Argument;
+import io.micronaut.jackson.databind.JacksonDatabindMapper;
+import io.micronaut.serde.data.SimpleBean;
+import io.micronaut.serde.jackson.JacksonJsonMapper;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+
+public class StartupBenchmark {
+
+    @Benchmark
+    @BenchmarkMode(Mode.SingleShotTime)
+    public Object fullStartupAndGetMapper(Holder1 holder) {
+        try (ApplicationContext ctx = ApplicationContext.run()) {
+            if (holder.stack == Stack.SERDE_JACKSON) {
+                return ctx.getBean(JacksonJsonMapper.class);
+            } else if (holder.stack == Stack.JACKSON_DATABIND) {
+                return ctx.getBean(JacksonDatabindMapper.class);
+            }
+            throw new IllegalStateException();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.SingleShotTime)
+    public Object fullStartupAndGetMapperReadBean(Holder1 holder) throws Exception {
+        try (ApplicationContext ctx = ApplicationContext.run()) {
+            if (holder.stack == Stack.SERDE_JACKSON) {
+                return ctx.getBean(JacksonJsonMapper.class).readValue("{}", Argument.of(SimpleBean.class));
+            } else if (holder.stack == Stack.JACKSON_DATABIND) {
+                return ctx.getBean(JacksonDatabindMapper.class).readValue("{}", Argument.of(SimpleBean.class));
+            }
+            throw new IllegalStateException();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.SingleShotTime)
+    public Object getMapper(Holder2 holder) {
+        if (holder.stack == Stack.SERDE_JACKSON) {
+            return holder.ctx.getBean(JacksonJsonMapper.class);
+        } else if (holder.stack == Stack.JACKSON_DATABIND) {
+            return holder.ctx.getBean(JacksonDatabindMapper.class);
+        }
+        throw new IllegalStateException();
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.SingleShotTime)
+    public Object getMapperReadBean(Holder2 holder) throws Exception {
+        if (holder.stack == Stack.SERDE_JACKSON) {
+            return holder.ctx.getBean(JacksonJsonMapper.class).readValue("{}", Argument.of(SimpleBean.class));
+        } else if (holder.stack == Stack.JACKSON_DATABIND) {
+            return holder.ctx.getBean(JacksonDatabindMapper.class).readValue("{}", Argument.of(SimpleBean.class));
+        }
+        throw new IllegalStateException();
+    }
+
+    public static void main(String[] args) {
+        try (ApplicationContext ctx = ApplicationContext.run()) {
+            ctx.getBean(JacksonJsonMapper.class);
+        }
+    }
+
+
+    @State(Scope.Thread)
+    public static class Holder1 {
+        @Param({
+            "SERDE_JACKSON",
+            "JACKSON_DATABIND"
+
+        })
+        Stack stack = Stack.SERDE_JACKSON;
+
+    }
+
+    @State(Scope.Thread)
+    public static class Holder2 {
+        @Param({
+            "SERDE_JACKSON",
+            "JACKSON_DATABIND"
+        })
+        Stack stack = Stack.SERDE_JACKSON;
+
+        ApplicationContext ctx;
+
+        @Setup
+        public void setUp() {
+            ctx = ApplicationContext.run();
+        }
+
+        @TearDown
+        public void tearDown() {
+            ctx.close();
+        }
+    }
+
+    public enum Stack {
+        SERDE_JACKSON,
+        JACKSON_DATABIND,
+    }
+
+}
diff --git a/benchmarks/src/jmh/java/io/micronaut/serde/data/SimpleBean.java b/benchmarks/src/jmh/java/io/micronaut/serde/data/SimpleBean.java
new file mode 100644
index 000000000..85b24e23a
--- /dev/null
+++ b/benchmarks/src/jmh/java/io/micronaut/serde/data/SimpleBean.java
@@ -0,0 +1,26 @@
+package io.micronaut.serde.data;
+
+import io.micronaut.serde.annotation.Serdeable;
+
+@Serdeable
+public class SimpleBean {
+
+    private Long id;
+    private String name;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}