Repository: focus-shift/jollyday
Pull request #473 (2024-02-29 15:08:10)

Add benchmark tests via jmh
* Tests should only run separately from other tests
* Should have reference scores based on GitHub actions
* Tests should only fail if e.g. more than 5% slower than reference score

refs #460 

sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=focus-shift_jollyday&pullRequest=473&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=focus-shift_jollyday&pullRequest=473&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=focus-shift_jollyday&pullRequest=473)



Patch:
diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml
new file mode 100644
index 00000000..94ae0493
--- /dev/null
+++ b/.github/workflows/benchmark.yml
@@ -0,0 +1,29 @@
+name: Benchmark
+
+on:
+  schedule:
+    - cron: "15 0 * * *"
+  push:
+    branches:
+      - main
+  pull_request:
+  workflow_dispatch:
+
+env:
+  MAVEN_ARGS: "--no-transfer-progress --errors --fail-at-end --show-version"
+
+jobs:
+  build:
+    name: benchmark
+    runs-on: 'ubuntu-latest'
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+      - name: JDK
+        uses: actions/setup-java@v4
+        with:
+          distribution: 'temurin'
+          java-version: '11'
+          cache: 'maven'
+      - name: Build
+        run: ./mvnw clean verify -Dtests.groups=BenchmarkTest
diff --git a/pom.xml b/pom.xml
index f7ccb7c0..a17bbdae 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,10 +36,13 @@
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <java.version>11</java.version>
 
+    <tests.groups>!BenchmarkTest</tests.groups>
+
     <junit.version>5.10.2</junit.version>
     <mockito.version>5.10.0</mockito.version>
     <assertj.version>3.25.3</assertj.version>
     <jqwik.version>1.8.3</jqwik.version>
+    <jmh.version>1.37</jmh.version>
 
     <!--suppress UnresolvedMavenProperty - for IDEA-->
     <sonar.coverage.jacoco.xmlReportPaths>
@@ -139,6 +142,20 @@
         <version>1.5.0</version>
         <scope>test</scope>
       </dependency>
+
+      <!-- jmh -->
+      <dependency>
+        <groupId>org.openjdk.jmh</groupId>
+        <artifactId>jmh-core</artifactId>
+        <version>${jmh.version}</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.openjdk.jmh</groupId>
+        <artifactId>jmh-generator-annprocess</artifactId>
+        <version>${jmh.version}</version>
+        <scope>test</scope>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 
@@ -155,6 +172,9 @@
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-surefire-plugin</artifactId>
           <version>3.2.5</version>
+          <configuration>
+            <groups>${tests.groups}</groups>
+          </configuration>
         </plugin>
 
         <plugin>


Test patch:
diff --git a/jollyday-tests/pom.xml b/jollyday-tests/pom.xml
index 25619d2b..f79d6784 100644
--- a/jollyday-tests/pom.xml
+++ b/jollyday-tests/pom.xml
@@ -56,6 +56,16 @@
       <version>0.1.2</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.openjdk.jmh</groupId>
+      <artifactId>jmh-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.openjdk.jmh</groupId>
+      <artifactId>jmh-generator-annprocess</artifactId>
+      <scope>test</scope>
+    </dependency>
 
     <!-- Logging -->
     <dependency>
diff --git a/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/Benchmarks.java b/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/Benchmarks.java
new file mode 100644
index 00000000..93eb1e44
--- /dev/null
+++ b/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/Benchmarks.java
@@ -0,0 +1,19 @@
+package de.focus_shift.jollyday.tests;
+
+import org.openjdk.jmh.results.RunResult;
+
+import java.text.DecimalFormat;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public abstract class Benchmarks {
+
+  protected static void assertDeviationWithin(final RunResult result, final double referenceScore, final double maxDeviationInPercent) {
+    final double score = result.getPrimaryResult().getScore();
+    final double minimumValidScore = referenceScore - (referenceScore * maxDeviationInPercent);
+
+    assertThat(score)
+      .withFailMessage("The score (%s) must be greater than the minimum valid score (%s)", score, minimumValidScore)
+      .isGreaterThan(minimumValidScore);
+  }
+}
diff --git a/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/HolidayManagerCreatingBenchmarkTest.java b/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/HolidayManagerCreatingBenchmarkTest.java
new file mode 100644
index 00000000..2c1464bd
--- /dev/null
+++ b/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/HolidayManagerCreatingBenchmarkTest.java
@@ -0,0 +1,78 @@
+package de.focus_shift.jollyday.tests;
+
+import de.focus_shift.jollyday.core.HolidayManager;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.results.RunResult;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import static de.focus_shift.jollyday.core.ManagerParameters.create;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@BenchmarkMode(Mode.Throughput)
+@Fork(3)
+@Warmup(iterations = 5, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 5, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
+public class HolidayManagerCreatingBenchmarkTest extends Benchmarks {
+
+  static final Map<String, Double> REFERENCE_SCORES = Map.of(
+    "benchmarkCreateHolidayManagerWithCachingEnabled", 54_000.00,
+    "benchmarkCreateHolidayManagerWithCachingDisabled", 1_200.00
+  );
+
+  @Benchmark
+  public static HolidayManager benchmarkCreateHolidayManagerWithCachingEnabled() {
+    return HolidayManager.getInstance(create("test"));
+  }
+
+  @State(Scope.Thread)
+  public static class HolidayManagerCacheDisabledState {
+    @Setup(Level.Trial)
+    public void doSetup() {
+      HolidayManager.setManagerCachingEnabled(false);
+    }
+
+    @TearDown(Level.Trial)
+    public void doTearDown() {
+      HolidayManager.setManagerCachingEnabled(true);
+    }
+  }
+
+  @Benchmark
+  public static HolidayManager benchmarkCreateHolidayManagerWithCachingDisabled(final HolidayManagerCacheDisabledState state) {
+    return HolidayManager.getInstance(create("test"));
+  }
+
+  @Test
+  @Tag("BenchmarkTest")
+  void runJmhBenchmark() throws RunnerException {
+    final Options opt = new OptionsBuilder()
+      .include(HolidayManagerCreatingBenchmarkTest.class.getSimpleName())
+      .build();
+
+    final Collection<RunResult> runResults = new Runner(opt).run();
+    assertThat(runResults).isNotEmpty();
+
+    for (RunResult runResult : runResults) {
+      assertDeviationWithin(runResult, REFERENCE_SCORES.get(runResult.getPrimaryResult().getLabel()), 0.05);
+    }
+  }
+}
diff --git a/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/HolidayManagerGetHolidayBenchmarkTest.java b/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/HolidayManagerGetHolidayBenchmarkTest.java
new file mode 100644
index 00000000..5c30ef0b
--- /dev/null
+++ b/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/HolidayManagerGetHolidayBenchmarkTest.java
@@ -0,0 +1,60 @@
+package de.focus_shift.jollyday.tests;
+
+import de.focus_shift.jollyday.core.Holiday;
+import de.focus_shift.jollyday.core.HolidayManager;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.results.RunResult;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import static de.focus_shift.jollyday.core.ManagerParameters.create;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@BenchmarkMode(Mode.Throughput)
+@Fork(3)
+@Warmup(iterations = 5, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 5, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
+public class HolidayManagerGetHolidayBenchmarkTest extends Benchmarks {
+
+  private static final double REFERENCE_SCORE = 45_000.00;
+
+  @State(Scope.Thread)
+  public static class HolidayManagerState {
+    public final HolidayManager holidayManager = HolidayManager.getInstance(create("test"));
+  }
+
+  @Benchmark
+  public static Set<Holiday> benchmarkGetHolidays(final HolidayManagerState holidayManagerState) {
+    return holidayManagerState.holidayManager.getHolidays(2010);
+  }
+
+  @Test
+  @Tag("BenchmarkTest")
+  void runJmhBenchmark() throws RunnerException {
+    final Options opt = new OptionsBuilder()
+      .include(HolidayManagerGetHolidayBenchmarkTest.class.getSimpleName())
+      .build();
+
+    final Collection<RunResult> runResults = new Runner(opt).run();
+    assertThat(runResults).isNotEmpty();
+
+    for (RunResult runResult : runResults) {
+      assertDeviationWithin(runResult, REFERENCE_SCORE, 0.05);
+    }
+  }
+}
diff --git a/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/HolidayManagerIsHolidayBenchmarkTest.java b/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/HolidayManagerIsHolidayBenchmarkTest.java
new file mode 100644
index 00000000..3ace013f
--- /dev/null
+++ b/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/HolidayManagerIsHolidayBenchmarkTest.java
@@ -0,0 +1,59 @@
+package de.focus_shift.jollyday.tests;
+
+import de.focus_shift.jollyday.core.HolidayManager;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.results.RunResult;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.time.LocalDate;
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
+
+import static de.focus_shift.jollyday.core.ManagerParameters.create;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@BenchmarkMode(Mode.Throughput)
+@Fork(3)
+@Warmup(iterations = 5, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 5, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
+public class HolidayManagerIsHolidayBenchmarkTest extends Benchmarks {
+
+  private static final double REFERENCE_SCORE = 8_300_000.000;
+
+  @State(Scope.Thread)
+  public static class HolidayManagerState {
+    public final HolidayManager holidayManager = HolidayManager.getInstance(create("test"));
+  }
+
+  @Benchmark
+  public static boolean benchmarkIsHoliday(final HolidayManagerState holidayManagerState) {
+    return holidayManagerState.holidayManager.isHoliday(LocalDate.of(2010, 1, 1));
+  }
+
+  @Test
+  @Tag("BenchmarkTest")
+  void runJmhBenchmark() throws RunnerException {
+    final Options opt = new OptionsBuilder()
+      .include(HolidayManagerIsHolidayBenchmarkTest.class.getSimpleName())
+      .build();
+
+    final Collection<RunResult> runResults = new Runner(opt).run();
+    assertThat(runResults).isNotEmpty();
+
+    for (RunResult runResult : runResults) {
+      assertDeviationWithin(runResult, REFERENCE_SCORE, 0.05);
+    }
+  }
+}
diff --git a/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/HolidayManagerPerformanceTest.java b/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/HolidayManagerPerformanceTest.java
deleted file mode 100644
index 8562790c..00000000
--- a/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/HolidayManagerPerformanceTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package de.focus_shift.jollyday.tests;
-
-import de.focus_shift.jollyday.core.HolidayManager;
-import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.time.LocalDate;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.atomic.AtomicLong;
-
-import static de.focus_shift.jollyday.core.ManagerParameters.create;
-import static java.util.concurrent.TimeUnit.SECONDS;
-
-class HolidayManagerPerformanceTest {
-
-  private static final Logger LOG = LoggerFactory.getLogger(HolidayManagerPerformanceTest.class);
-
-  @Test
-  void testIsHolidayPerformanceMultiThread() throws InterruptedException {
-
-    LocalDate date = LocalDate.of(2010, 1, 1);
-    final AtomicLong count = new AtomicLong(0);
-    final AtomicLong sumDuration = new AtomicLong(0);
-
-    final ExecutorService executorService = Executors.newCachedThreadPool();
-    while (date.getYear() < 2013) {
-      final LocalDate localDate = date;
-      executorService.submit(() -> {
-        final long start = System.currentTimeMillis();
-
-        final HolidayManager holidayManager = HolidayManager.getInstance(create("test"));
-        holidayManager.isHoliday(localDate);
-
-        final long duration = System.currentTimeMillis() - start;
-        count.incrementAndGet();
-        sumDuration.addAndGet(duration);
-      });
-      date = date.plusDays(1);
-    }
-    executorService.shutdown();
-    executorService.awaitTermination(5, SECONDS);
-
-    LOG.info("isHoliday took {} millis average tested with {} calls.", sumDuration.doubleValue() / count.doubleValue(), count.longValue());
-  }
-}