Skip to content

Commit ea7eac5

Browse files
committed
Hibernate ORM - Generate proxies in parallel
1 parent b21cf5f commit ea7eac5

File tree

1 file changed

+37
-20
lines changed

1 file changed

+37
-20
lines changed

extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmProcessor.java

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
import java.util.Properties;
3030
import java.util.Set;
3131
import java.util.TreeSet;
32+
import java.util.concurrent.CompletableFuture;
33+
import java.util.concurrent.ConcurrentLinkedDeque;
34+
import java.util.concurrent.ExecutionException;
35+
import java.util.concurrent.ExecutorService;
36+
import java.util.concurrent.Future;
3237
import java.util.function.BiConsumer;
3338
import java.util.stream.Collectors;
3439

@@ -464,7 +469,8 @@ public BytecodeRecorderConstantDefinitionBuildItem pregenProxies(
464469
List<PersistenceUnitDescriptorBuildItem> persistenceUnitDescriptorBuildItems,
465470
List<AdditionalJpaModelBuildItem> additionalJpaModelBuildItems,
466471
BuildProducer<GeneratedClassBuildItem> generatedClassBuildItemBuildProducer,
467-
LiveReloadBuildItem liveReloadBuildItem) {
472+
LiveReloadBuildItem liveReloadBuildItem,
473+
ExecutorService buildExecutor) throws ExecutionException, InterruptedException {
468474
Set<String> managedClassAndPackageNames = new HashSet<>(jpaModel.getEntityClassNames());
469475
for (PersistenceUnitDescriptorBuildItem pud : persistenceUnitDescriptorBuildItems) {
470476
// Note: getManagedClassNames() can also return *package* names
@@ -478,9 +484,9 @@ public BytecodeRecorderConstantDefinitionBuildItem pregenProxies(
478484
managedClassAndPackageNames.add(additionalJpaModelBuildItem.getClassName());
479485
}
480486

481-
PreGeneratedProxies proxyDefinitions = generatedProxies(managedClassAndPackageNames,
487+
PreGeneratedProxies proxyDefinitions = generateProxies(managedClassAndPackageNames,
482488
indexBuildItem.getIndex(), transformedClassesBuildItem,
483-
generatedClassBuildItemBuildProducer, liveReloadBuildItem);
489+
generatedClassBuildItemBuildProducer, liveReloadBuildItem, buildExecutor);
484490

485491
// Make proxies available through a constant;
486492
// this is a hack to avoid introducing circular dependencies between build steps.
@@ -1371,53 +1377,62 @@ private static MultiTenancyStrategy getMultiTenancyStrategy(Optional<String> mul
13711377
return multiTenancyStrategy;
13721378
}
13731379

1374-
private PreGeneratedProxies generatedProxies(Set<String> managedClassAndPackageNames, IndexView combinedIndex,
1380+
private PreGeneratedProxies generateProxies(Set<String> managedClassAndPackageNames, IndexView combinedIndex,
13751381
TransformedClassesBuildItem transformedClassesBuildItem,
13761382
BuildProducer<GeneratedClassBuildItem> generatedClassBuildItemBuildProducer,
1377-
LiveReloadBuildItem liveReloadBuildItem) {
1383+
LiveReloadBuildItem liveReloadBuildItem,
1384+
ExecutorService buildExecutor) throws ExecutionException, InterruptedException {
13781385
ProxyCache proxyCache = liveReloadBuildItem.getContextObject(ProxyCache.class);
13791386
if (proxyCache == null) {
13801387
proxyCache = new ProxyCache();
13811388
liveReloadBuildItem.setContextObject(ProxyCache.class, proxyCache);
13821389
}
1383-
Set<String> changedClasses = Collections.emptySet();
1390+
Set<String> changedClasses = Set.of();
13841391
if (liveReloadBuildItem.getChangeInformation() != null) {
13851392
changedClasses = liveReloadBuildItem.getChangeInformation().getChangedClasses();
13861393
} else {
13871394
//we don't have class change info, invalidate the cache
13881395
proxyCache.cache.clear();
13891396
}
13901397
//create a map of entity to proxy type
1391-
PreGeneratedProxies preGeneratedProxies = new PreGeneratedProxies();
13921398
TypePool transformedClassesTypePool = createTransformedClassesTypePool(transformedClassesBuildItem,
13931399
managedClassAndPackageNames);
1400+
1401+
PreGeneratedProxies preGeneratedProxies = new PreGeneratedProxies();
1402+
13941403
try (ProxyBuildingHelper proxyHelper = new ProxyBuildingHelper(transformedClassesTypePool)) {
1404+
final ConcurrentLinkedDeque<Future<CachedProxy>> generatedProxyQueue = new ConcurrentLinkedDeque<>();
1405+
Set<String> proxyInterfaceNames = Set.of(ClassNames.HIBERNATE_PROXY.toString());
1406+
13951407
for (String managedClassOrPackageName : managedClassAndPackageNames) {
1396-
CachedProxy result;
13971408
if (proxyCache.cache.containsKey(managedClassOrPackageName)
13981409
&& !isModified(managedClassOrPackageName, changedClasses, combinedIndex)) {
1399-
result = proxyCache.cache.get(managedClassOrPackageName);
1410+
CachedProxy proxy = proxyCache.cache.get(managedClassOrPackageName);
1411+
generatedProxyQueue.add(CompletableFuture.completedFuture(proxy));
14001412
} else {
1401-
Set<String> proxyInterfaceNames = new TreeSet<>();
1402-
proxyInterfaceNames.add(ClassNames.HIBERNATE_PROXY.toString()); //always added
14031413
if (!proxyHelper.isProxiable(combinedIndex.getClassByName(managedClassOrPackageName))) {
14041414
// we need to make sure the actual class is proxiable
14051415
continue;
14061416
}
1407-
final String mappedClass = managedClassOrPackageName;
1408-
DynamicType.Unloaded<?> unloaded = proxyHelper.buildUnloadedProxy(mappedClass, proxyInterfaceNames);
1409-
result = new CachedProxy(unloaded, proxyInterfaceNames);
1410-
proxyCache.cache.put(managedClassOrPackageName, result);
1417+
generatedProxyQueue.add(buildExecutor.submit(() -> {
1418+
DynamicType.Unloaded<?> unloaded = proxyHelper.buildUnloadedProxy(managedClassOrPackageName,
1419+
proxyInterfaceNames);
1420+
return new CachedProxy(managedClassOrPackageName, unloaded, proxyInterfaceNames);
1421+
}));
14111422
}
1412-
for (Entry<TypeDescription, byte[]> i : result.proxyDef.getAllTypes().entrySet()) {
1423+
}
1424+
1425+
for (Future<CachedProxy> proxyFuture : generatedProxyQueue) {
1426+
CachedProxy proxy = proxyFuture.get();
1427+
for (Entry<TypeDescription, byte[]> i : proxy.proxyDef.getAllTypes().entrySet()) {
14131428
generatedClassBuildItemBuildProducer
14141429
.produce(new GeneratedClassBuildItem(true, i.getKey().getName(), i.getValue()));
14151430
}
1416-
preGeneratedProxies.getProxies().put(managedClassOrPackageName,
1417-
new PreGeneratedProxies.ProxyClassDetailsHolder(result.proxyDef.getTypeDescription().getName(),
1418-
result.interfaces));
1431+
preGeneratedProxies.getProxies().put(proxy.managedClassName, new PreGeneratedProxies.ProxyClassDetailsHolder(
1432+
proxy.proxyDef.getTypeDescription().getName(), proxy.interfaces));
14191433
}
14201434
}
1435+
14211436
return preGeneratedProxies;
14221437
}
14231438

@@ -1473,10 +1488,12 @@ private static final class ProxyCache {
14731488
}
14741489

14751490
static final class CachedProxy {
1491+
final String managedClassName;
14761492
final DynamicType.Unloaded<?> proxyDef;
14771493
final Set<String> interfaces;
14781494

1479-
CachedProxy(DynamicType.Unloaded<?> proxyDef, Set<String> interfaces) {
1495+
CachedProxy(String managedClassName, DynamicType.Unloaded<?> proxyDef, Set<String> interfaces) {
1496+
this.managedClassName = managedClassName;
14801497
this.proxyDef = proxyDef;
14811498
this.interfaces = interfaces;
14821499
}

0 commit comments

Comments
 (0)