Skip to content

Commit 90df7ea

Browse files
committed
Use a Caffeine based cache for Hibernate's InternalCache implementations
1 parent 5bd305c commit 90df7ea

File tree

6 files changed

+104
-12
lines changed

6 files changed

+104
-12
lines changed

extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/registry/PreconfiguredServiceRegistryBuilder.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import org.hibernate.engine.jdbc.internal.SqlStatementLoggerInitiator;
2121
import org.hibernate.event.internal.EntityCopyObserverFactoryInitiator;
2222
import org.hibernate.integrator.spi.Integrator;
23-
import org.hibernate.internal.util.cache.InternalCacheFactoryInitiator;
2423
import org.hibernate.loader.ast.internal.BatchLoaderFactoryInitiator;
2524
import org.hibernate.persister.internal.PersisterClassResolverInitiator;
2625
import org.hibernate.persister.internal.PersisterFactoryInitiator;
@@ -50,6 +49,7 @@
5049
import io.quarkus.hibernate.orm.runtime.service.QuarkusRuntimeInitDialectFactoryInitiator;
5150
import io.quarkus.hibernate.orm.runtime.service.QuarkusRuntimeInitDialectResolverInitiator;
5251
import io.quarkus.hibernate.orm.runtime.service.bytecodeprovider.QuarkusRuntimeBytecodeProviderInitiator;
52+
import io.quarkus.hibernate.orm.runtime.service.internalcache.QuarkusInternalCacheFactoryInitiator;
5353

5454
/**
5555
* Helps to instantiate a ServiceRegistryBuilder from a previous state. This
@@ -249,8 +249,8 @@ private static List<StandardServiceInitiator<?>> buildQuarkusServiceInitiatorLis
249249
// Default implementation
250250
serviceInitiators.add(SqlStatementLoggerInitiator.INSTANCE);
251251

252-
// Default implementation -- TODO use Caffeine instead
253-
serviceInitiators.add(InternalCacheFactoryInitiator.INSTANCE);
252+
// Custom Quarkus implementation: overrides the internal cache to leverage Caffeine
253+
serviceInitiators.add(QuarkusInternalCacheFactoryInitiator.INSTANCE);
254254

255255
serviceInitiators.trimToSize();
256256
return serviceInitiators;

extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/service/StandardHibernateORMInitiatorListProvider.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator;
1515
import org.hibernate.engine.jdbc.internal.SqlStatementLoggerInitiator;
1616
import org.hibernate.event.internal.EntityCopyObserverFactoryInitiator;
17-
import org.hibernate.internal.util.cache.InternalCacheFactoryInitiator;
1817
import org.hibernate.loader.ast.internal.BatchLoaderFactoryInitiator;
1918
import org.hibernate.persister.internal.PersisterClassResolverInitiator;
2019
import org.hibernate.persister.internal.PersisterFactoryInitiator;
@@ -30,6 +29,7 @@
3029
import io.quarkus.hibernate.orm.runtime.customized.BootstrapOnlyProxyFactoryFactoryInitiator;
3130
import io.quarkus.hibernate.orm.runtime.customized.QuarkusJndiServiceInitiator;
3231
import io.quarkus.hibernate.orm.runtime.customized.QuarkusJtaPlatformInitiator;
32+
import io.quarkus.hibernate.orm.runtime.service.internalcache.QuarkusInternalCacheFactoryInitiator;
3333

3434
/**
3535
* Here we define the list of standard Service Initiators to be used by
@@ -110,8 +110,8 @@ public List<StandardServiceInitiator<?>> initialInitiatorList() {
110110
// Default implementation
111111
serviceInitiators.add(SqlStatementLoggerInitiator.INSTANCE);
112112

113-
// Default implementation -- TODO use Caffeine instead
114-
serviceInitiators.add(InternalCacheFactoryInitiator.INSTANCE);
113+
// Custom Quarkus implementation: overrides the internal cache to leverage Caffeine
114+
serviceInitiators.add(QuarkusInternalCacheFactoryInitiator.INSTANCE);
115115

116116
serviceInitiators.trimToSize();
117117

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package io.quarkus.hibernate.orm.runtime.service.internalcache;
2+
3+
import java.util.function.Function;
4+
5+
import org.hibernate.internal.util.cache.InternalCache;
6+
7+
import com.github.benmanes.caffeine.cache.Cache;
8+
9+
final class QuarkusInternalCache<K, V> implements InternalCache<K, V> {
10+
11+
private final Cache<K, V> cache;
12+
13+
public QuarkusInternalCache(Cache<K, V> caffeineCache) {
14+
this.cache = caffeineCache;
15+
}
16+
17+
@Override
18+
public int heldElementsEstimate() {
19+
return Math.toIntExact(cache.estimatedSize());
20+
}
21+
22+
@Override
23+
public V get(K key) {
24+
return cache.getIfPresent(key);
25+
}
26+
27+
@Override
28+
public void put(K key, V value) {
29+
cache.put(key, value);
30+
}
31+
32+
@Override
33+
public void clear() {
34+
cache.invalidateAll();
35+
cache.cleanUp();
36+
}
37+
38+
@Override
39+
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
40+
return cache.get(key, mappingFunction);
41+
}
42+
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.quarkus.hibernate.orm.runtime.service.internalcache;
2+
3+
import java.util.Map;
4+
5+
import org.hibernate.boot.registry.StandardServiceInitiator;
6+
import org.hibernate.internal.util.cache.InternalCache;
7+
import org.hibernate.internal.util.cache.InternalCacheFactory;
8+
import org.hibernate.service.spi.ServiceRegistryImplementor;
9+
10+
import com.github.benmanes.caffeine.cache.Cache;
11+
import com.github.benmanes.caffeine.cache.Caffeine;
12+
13+
/**
14+
* Override of {@link org.hibernate.internal.util.cache.InternalCacheFactoryInitiator}:
15+
* this switches the internal cache implementation (currently used for some stats and, crucially, for the
16+
* {@link org.hibernate.query.spi.QueryInterpretationCache}
17+
* to use Caffeine rather than the legacy implementation Hibernate ORM normally uses, which is based on the excellent LIRS
18+
* algorithm but which we
19+
* plan to deprecate in favour of modern caching libraries.
20+
* See also <a href="https://en.wikipedia.org/wiki/LIRS_caching_algorithm">LIRS</a> and
21+
* <a href="https://github.com/ben-manes/caffeine/wiki/Efficiency">Caffeine, efficiency</a>.
22+
*/
23+
public final class QuarkusInternalCacheFactoryInitiator implements StandardServiceInitiator<InternalCacheFactory> {
24+
25+
public static final QuarkusInternalCacheFactoryInitiator INSTANCE = new QuarkusInternalCacheFactoryInitiator();
26+
27+
private QuarkusInternalCacheFactoryInitiator() {
28+
}
29+
30+
@Override
31+
public InternalCacheFactory initiateService(Map<String, Object> configurationValues, ServiceRegistryImplementor registry) {
32+
return new QuarkusInternalCacheFactory();
33+
}
34+
35+
@Override
36+
public Class<InternalCacheFactory> getServiceInitiated() {
37+
return InternalCacheFactory.class;
38+
}
39+
40+
private static class QuarkusInternalCacheFactory implements InternalCacheFactory {
41+
@Override
42+
public <K, V> InternalCache<K, V> createInternalCache(int intendedApproximateSize) {
43+
final Cache<K, V> caffeineCache = Caffeine.newBuilder()
44+
.maximumSize(intendedApproximateSize)
45+
.build();
46+
return new QuarkusInternalCache<>(caffeineCache);
47+
}
48+
}
49+
}

extensions/hibernate-reactive/runtime/src/main/java/io/quarkus/hibernate/reactive/runtime/boot/registry/PreconfiguredReactiveServiceRegistryBuilder.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import org.hibernate.engine.jdbc.internal.SqlStatementLoggerInitiator;
2020
import org.hibernate.event.internal.EntityCopyObserverFactoryInitiator;
2121
import org.hibernate.integrator.spi.Integrator;
22-
import org.hibernate.internal.util.cache.InternalCacheFactoryInitiator;
2322
import org.hibernate.persister.internal.PersisterFactoryInitiator;
2423
import org.hibernate.property.access.internal.PropertyAccessStrategyResolverInitiator;
2524
import org.hibernate.reactive.engine.jdbc.mutation.internal.ReactiveMutationExecutorServiceInitiator;
@@ -53,6 +52,7 @@
5352
import io.quarkus.hibernate.orm.runtime.service.QuarkusRuntimeInitDialectFactoryInitiator;
5453
import io.quarkus.hibernate.orm.runtime.service.QuarkusRuntimeInitDialectResolverInitiator;
5554
import io.quarkus.hibernate.orm.runtime.service.bytecodeprovider.QuarkusRuntimeBytecodeProviderInitiator;
55+
import io.quarkus.hibernate.orm.runtime.service.internalcache.QuarkusInternalCacheFactoryInitiator;
5656
import io.quarkus.hibernate.reactive.runtime.customized.CheckingVertxContextInitiator;
5757
import io.quarkus.hibernate.reactive.runtime.customized.QuarkusNoJdbcConnectionProviderInitiator;
5858

@@ -251,8 +251,8 @@ private static List<StandardServiceInitiator<?>> buildQuarkusServiceInitiatorLis
251251
// Custom for Hibernate Reactive: BatchLoaderFactory
252252
serviceInitiators.add(ReactiveBatchLoaderFactoryInitiator.INSTANCE);
253253

254-
// Default implementation -- TODO use Caffeine instead
255-
serviceInitiators.add(InternalCacheFactoryInitiator.INSTANCE);
254+
// Custom Quarkus implementation: overrides the internal cache to leverage Caffeine
255+
serviceInitiators.add(QuarkusInternalCacheFactoryInitiator.INSTANCE);
256256

257257
serviceInitiators.trimToSize();
258258
return serviceInitiators;

extensions/hibernate-reactive/runtime/src/main/java/io/quarkus/hibernate/reactive/runtime/boot/registry/ReactiveHibernateInitiatorListProvider.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator;
1515
import org.hibernate.engine.jdbc.internal.SqlStatementLoggerInitiator;
1616
import org.hibernate.event.internal.EntityCopyObserverFactoryInitiator;
17-
import org.hibernate.internal.util.cache.InternalCacheFactoryInitiator;
1817
import org.hibernate.persister.internal.PersisterFactoryInitiator;
1918
import org.hibernate.property.access.internal.PropertyAccessStrategyResolverInitiator;
2019
import org.hibernate.reactive.loader.ast.internal.ReactiveBatchLoaderFactoryInitiator;
@@ -37,6 +36,7 @@
3736
import io.quarkus.hibernate.orm.runtime.service.QuarkusRegionFactoryInitiator;
3837
import io.quarkus.hibernate.orm.runtime.service.QuarkusStaticInitDialectFactoryInitiator;
3938
import io.quarkus.hibernate.orm.runtime.service.StandardHibernateORMInitiatorListProvider;
39+
import io.quarkus.hibernate.orm.runtime.service.internalcache.QuarkusInternalCacheFactoryInitiator;
4040
import io.quarkus.hibernate.reactive.runtime.customized.QuarkusNoJdbcConnectionProviderInitiator;
4141

4242
/**
@@ -124,8 +124,8 @@ public List<StandardServiceInitiator<?>> initialInitiatorList() {
124124
// Custom for Hibernate Reactive: BatchLoaderFactory
125125
serviceInitiators.add(ReactiveBatchLoaderFactoryInitiator.INSTANCE);
126126

127-
// Default implementation -- TODO use Caffeine instead
128-
serviceInitiators.add(InternalCacheFactoryInitiator.INSTANCE);
127+
// Custom Quarkus implementation: overrides the internal cache to leverage Caffeine
128+
serviceInitiators.add(QuarkusInternalCacheFactoryInitiator.INSTANCE);
129129

130130
serviceInitiators.trimToSize();
131131
return serviceInitiators;

0 commit comments

Comments
 (0)