From 998e0a5b815245d4042614e864d669f22ec7499e Mon Sep 17 00:00:00 2001 From: Raghav Jha Date: Tue, 5 Feb 2019 17:45:51 +0530 Subject: [PATCH] BAEL-2456 Hibernate Query Plan Cache --- persistence-modules/hibernate5/pom.xml | 13 ++- .../QueryPlanCacheBenchmark.java | 106 ++++++++++++++++++ .../QueryPlanCacheUnitTest.java | 105 ----------------- 3 files changed, 115 insertions(+), 109 deletions(-) create mode 100644 persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/queryplancache/QueryPlanCacheBenchmark.java delete mode 100644 persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/queryplancache/QueryPlanCacheUnitTest.java diff --git a/persistence-modules/hibernate5/pom.xml b/persistence-modules/hibernate5/pom.xml index 6b9a9abbe5..a09669c8b5 100644 --- a/persistence-modules/hibernate5/pom.xml +++ b/persistence-modules/hibernate5/pom.xml @@ -74,9 +74,14 @@ ${hibernate.version} - io.dropwizard.metrics - metrics-core - ${dropwizard-metrics.version} + org.openjdk.jmh + jmh-core + ${openjdk-jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${openjdk-jmh.version} @@ -97,7 +102,7 @@ 1.4.196 3.8.0 2.9.7 - 4.0.5 + 1.21 diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/queryplancache/QueryPlanCacheBenchmark.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/queryplancache/QueryPlanCacheBenchmark.java new file mode 100644 index 0000000000..13eae3d877 --- /dev/null +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/queryplancache/QueryPlanCacheBenchmark.java @@ -0,0 +1,106 @@ +package com.baeldung.hibernate.queryplancache; + +import com.baeldung.hibernate.HibernateUtil; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.jpa.QueryHints; +import org.hibernate.query.Query; +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.OutputTimeUnit; +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; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.runner.RunnerException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +public class QueryPlanCacheBenchmark { + + private static final Logger LOGGER = LoggerFactory.getLogger(QueryPlanCacheBenchmark.class); + + @State(Scope.Thread) + public static class QueryPlanCacheBenchMarkState { + @Param({"1", "2", "3"}) + public int planCacheSize; + + public Session session; + + @Setup + public void stateSetup() throws IOException { + LOGGER.info("State - Setup"); + session = initSession(planCacheSize); + LOGGER.info("State - Setup Complete"); + } + + private Session initSession(int planCacheSize) throws IOException { + Properties properties = HibernateUtil.getProperties(); + properties.put("hibernate.query.plan_cache_max_size", planCacheSize); + properties.put("hibernate.query.plan_parameter_metadata_max_size", planCacheSize); + SessionFactory sessionFactory = HibernateUtil.getSessionFactoryByProperties(properties); + return sessionFactory.openSession(); + } + + @TearDown + public void tearDownState() { + LOGGER.info("State - Teardown"); + SessionFactory sessionFactory = session.getSessionFactory(); + session.close(); + sessionFactory.close(); + LOGGER.info("State - Teardown complete"); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + @Fork(1) + @Warmup(iterations = 2) + @Measurement(iterations = 5) + public void givenQueryPlanCacheSize_thenCompileQueries(QueryPlanCacheBenchMarkState state, Blackhole blackhole) { + + Query query1 = findEmployeesByDepartmentNameQuery(state.session); + Query query2 = findEmployeesByDesignationQuery(state.session); + Query query3 = findDepartmentOfAnEmployeeQuery(state.session); + + blackhole.consume(query1); + blackhole.consume(query2); + blackhole.consume(query3); + + } + + private Query findEmployeesByDepartmentNameQuery(Session session) { + return session.createQuery("SELECT e FROM DeptEmployee e " + + "JOIN e.department WHERE e.department.name = :deptName") + .setMaxResults(30) + .setHint(QueryHints.HINT_FETCH_SIZE, 30); + } + + private Query findEmployeesByDesignationQuery(Session session) { + return session.createQuery("SELECT e FROM DeptEmployee e " + + "WHERE e.title = :designation") + .setHint(QueryHints.SPEC_HINT_TIMEOUT, 1000); + } + + private Query findDepartmentOfAnEmployeeQuery(Session session) { + return session.createQuery("SELECT e.department FROM DeptEmployee e " + + "JOIN e.department WHERE e.employeeNumber = :empId"); + + } + + public static void main(String... args) throws IOException, RunnerException { + //main-class to run the benchmark + org.openjdk.jmh.Main.main(args); + } +} diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/queryplancache/QueryPlanCacheUnitTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/queryplancache/QueryPlanCacheUnitTest.java deleted file mode 100644 index 68325c559f..0000000000 --- a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/queryplancache/QueryPlanCacheUnitTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.baeldung.hibernate.queryplancache; - -import com.baeldung.hibernate.HibernateUtil; -import com.codahale.metrics.Timer; -import com.codahale.metrics.UniformReservoir; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.jpa.QueryHints; -import org.hibernate.query.Query; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; -import java.util.concurrent.TimeUnit; - -@RunWith(Parameterized.class) -public class QueryPlanCacheUnitTest { - - private static final Logger LOGGER = LoggerFactory.getLogger(QueryPlanCacheUnitTest.class); - - @Parameterized.Parameters - public static List planCacheSize() { - List planCacheSizes = new ArrayList<>(); - - planCacheSizes.add(new Integer[]{1}); - planCacheSizes.add(new Integer[]{2}); - planCacheSizes.add(new Integer[]{3}); - - - return planCacheSizes; - } - - private Timer timer = new Timer(new UniformReservoir(9900)); - - private int planCacheSize; - - public QueryPlanCacheUnitTest(int planCacheSize) { - this.planCacheSize = planCacheSize; - } - - @Test - @Ignore - public void givenQueryPlanCacheSize_thenCompileQueries() throws IOException { - Session session = initSession(); - - //warm-up - for (int i = 0; i < 9900; i++) { - createFindEmployeesByDepartmentNameQuery(session); - createFindEmployeesByDesignationQuery(session); - createFindDepartmentOfAnEmployeeQuery(session); - } - - for (int i = 0; i < 3300; i++) { - long startTime = System.nanoTime(); - createFindEmployeesByDepartmentNameQuery(session); - timer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS); - - startTime = System.nanoTime(); - createFindEmployeesByDesignationQuery(session); - timer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS); - - startTime = System.nanoTime(); - createFindDepartmentOfAnEmployeeQuery(session); - timer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS); - } - - LOGGER.info("Query Plan Cache Size - {}, Time(Nanoseconds) - {}", planCacheSize, timer.getSnapshot().get95thPercentile()); - - } - - private Session initSession() throws IOException { - Properties properties = HibernateUtil.getProperties(); - properties.put("hibernate.query.plan_cache_max_size", planCacheSize); - properties.put("hibernate.query.plan_parameter_metadata_max_size", planCacheSize); - SessionFactory sessionFactory = HibernateUtil.getSessionFactoryByProperties(properties); - return sessionFactory.openSession(); - } - - private Query createFindEmployeesByDepartmentNameQuery(Session session) { - return session.createQuery("SELECT e FROM DeptEmployee e " + - "JOIN e.department WHERE e.department.name = :deptName") - .setMaxResults(30) - .setHint(QueryHints.HINT_FETCH_SIZE, 30); - } - - private Query createFindEmployeesByDesignationQuery(Session session) { - return session.createQuery("SELECT e FROM DeptEmployee e " + - "WHERE e.title = :designation") - .setHint(QueryHints.SPEC_HINT_TIMEOUT, 1000); - } - - private Query createFindDepartmentOfAnEmployeeQuery(Session session) { - return session.createQuery("SELECT e.department FROM DeptEmployee e " + - "JOIN e.department WHERE e.employeeNumber = :empId"); - - } - -}