Skip to content

Commit

Permalink
ArC build time perf improvement
Browse files Browse the repository at this point in the history
This removes the need to iterate over all beans when performing
resolution. For a project with 2k injection points this saves close to
0.5s on my desktop.
  • Loading branch information
stuartwdouglas committed Sep 21, 2021
1 parent ac7def7 commit a1ff159
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public class BeanDeployment {
private final Map<DotName, StereotypeInfo> stereotypes;

private final List<BeanInfo> beans;
private volatile Map<Type, List<BeanInfo>> beansByType = null;

private final List<InterceptorInfo> interceptors;
private final List<DecoratorInfo> decorators;
Expand Down Expand Up @@ -231,6 +232,7 @@ BeanRegistrar.RegistrationContext registerBeans(List<BeanRegistrar> beanRegistra
List<InjectionPointInfo> injectionPoints = new ArrayList<>();
this.beans.addAll(findBeans(initBeanDefiningAnnotations(beanDefiningAnnotations, stereotypes.keySet()), observers,
injectionPoints, jtaCapabilities));
beansByType = null;
// Note that we need to use view of the collections to reflect further additions, e.g. synthetic beans and observers
buildContextPut(Key.BEANS.asString(), Collections.unmodifiableList(beans));
buildContextPut(Key.OBSERVERS.asString(), Collections.unmodifiableList(observers));
Expand Down Expand Up @@ -375,6 +377,7 @@ private Set<BeanInfo> removeUnusedBeans(Set<BeanInfo> declaresObserver, List<Pre
allUnusedExclusions);
if (!removableBeans.isEmpty()) {
this.beans.removeAll(removableBeans);
beansByType = null;
this.removedBeans.addAll(removableBeans);
List<InjectionPointInfo> removableInjectionPoints = removableBeans.stream()
.flatMap(d -> d.getAllInjectionPoints().stream()).collect(Collectors.toList());
Expand Down Expand Up @@ -407,6 +410,29 @@ public Collection<BeanInfo> getBeans() {
return Collections.unmodifiableList(beans);
}

public Collection<BeanInfo> getBeansByType(Type type) {
Map<Type, List<BeanInfo>> byType = beansByType;
if (byType == null) {
synchronized (this) {
byType = beansByType;
if (byType == null) {
byType = new HashMap<>();
for (var i : beans) {
for (var t : i.types) {
byType.computeIfAbsent(t, (s) -> new ArrayList<>()).add(i);
}
}
this.beansByType = byType;
}
}
}
var ret = byType.get(type);
if (ret == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(ret);
}

public Collection<BeanInfo> getRemovedBeans() {
return Collections.unmodifiableSet(removedBeans);
}
Expand Down Expand Up @@ -1126,6 +1152,7 @@ private void addSyntheticBean(BeanInfo bean) {
}
}
beans.add(bean);
beansByType = null;
}

private void addSyntheticObserver(ObserverConfigurator configurator) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import io.quarkus.arc.processor.InjectionPointInfo.TypeAndQualifiers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -81,7 +82,11 @@ List<BeanInfo> resolve(TypeAndQualifiers typeAndQualifiers) {

private List<BeanInfo> findMatching(TypeAndQualifiers typeAndQualifiers) {
List<BeanInfo> resolved = new ArrayList<>();
for (BeanInfo b : beanDeployment.getBeans()) {
//optimisation for the simple class case
Collection<BeanInfo> potentialBeans = typeAndQualifiers.type.kind() == CLASS
? beanDeployment.getBeansByType(typeAndQualifiers.type)
: beanDeployment.getBeans();
for (BeanInfo b : potentialBeans) {
if (Beans.matches(b, typeAndQualifiers)) {
resolved.add(b);
}
Expand All @@ -91,7 +96,10 @@ private List<BeanInfo> findMatching(TypeAndQualifiers typeAndQualifiers) {

List<BeanInfo> findTypeMatching(Type type) {
List<BeanInfo> resolved = new ArrayList<>();
for (BeanInfo b : beanDeployment.getBeans()) {
//optimisation for the simple class case
Collection<BeanInfo> potentialBeans = type.kind() == CLASS ? beanDeployment.getBeansByType(type)
: beanDeployment.getBeans();
for (BeanInfo b : potentialBeans) {
if (Beans.matchesType(b, type)) {
resolved.add(b);
}
Expand Down

0 comments on commit a1ff159

Please sign in to comment.