Skip to content

Commit

Permalink
ArC - build time resolution improvement
Browse files Browse the repository at this point in the history
This PR follows-up on quarkusio#20290

The main improvements are:
- do not cache results for java.lang.Object - every bean has this type
- use optimized immutable structures; in most cases there will be a
single bean for a given type
- the key of the map is DotName (i.e. raw type name) so that it can be
used for parameterized types as well
  • Loading branch information
mkouba committed Oct 1, 2021
1 parent ec0a2d0 commit c30379f
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +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 volatile Map<DotName, List<BeanInfo>> beansByType;

private final List<InterceptorInfo> interceptors;
private final List<DecoratorInfo> decorators;
Expand Down Expand Up @@ -289,15 +289,32 @@ void init(Consumer<BytecodeTransformer> bytecodeTransformerConsumer,
}

private void initBeanByTypeMap() {
beansByType = new HashMap<>();
for (var bean : beans) {
for (var beanType : bean.types) {
beansByType.computeIfAbsent(beanType, (s) -> new ArrayList<>()).add(bean);
Map<DotName, List<BeanInfo>> map = new HashMap<>();
for (BeanInfo bean : beans) {
for (Type beanType : bean.types) {
if (DotNames.OBJECT.equals(beanType.name())) {
// Every bean has java.lang.Object - no need to cache results here
continue;
}
List<BeanInfo> beans = map.get(beanType.name());
if (beans == null) {
// Very often, there will be exactly one bean for a given type
map.put(beanType.name(), List.of(bean));
} else {
if (beans.size() == 1) {
map.put(beanType.name(), List.of(beans.get(0), bean));
} else {
BeanInfo[] array = new BeanInfo[beans.size() + 1];
for (int i = 0; i < beans.size(); i++) {
array[i] = beans.get(i);
}
array[beans.size()] = bean;
map.put(beanType.name(), List.of(array));
}
}
}
}
for (var e : beansByType.entrySet()) {
e.setValue(Collections.unmodifiableList(e.getValue()));
}
this.beansByType = map;
}

private void removeUnusedComponents(Set<BeanInfo> declaresObserver,
Expand Down Expand Up @@ -423,8 +440,8 @@ public Collection<BeanInfo> getBeans() {
return Collections.unmodifiableList(beans);
}

public Collection<BeanInfo> getBeansByType(Type type) {
var ret = beansByType.get(type);
Collection<BeanInfo> getBeansByRawType(DotName typeName) {
var ret = beansByType.get(typeName);
if (ret == null) {
return Collections.emptyList();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,7 @@ List<BeanInfo> resolve(TypeAndQualifiers typeAndQualifiers) {
private List<BeanInfo> findMatching(TypeAndQualifiers typeAndQualifiers) {
List<BeanInfo> resolved = new ArrayList<>();
//optimisation for the simple class case
Collection<BeanInfo> potentialBeans = typeAndQualifiers.type.kind() == CLASS
? beanDeployment.getBeansByType(typeAndQualifiers.type)
: beanDeployment.getBeans();
Collection<BeanInfo> potentialBeans = potentialBeans(typeAndQualifiers.type);
for (BeanInfo b : potentialBeans) {
if (Beans.matches(b, typeAndQualifiers)) {
resolved.add(b);
Expand All @@ -97,8 +95,7 @@ private List<BeanInfo> findMatching(TypeAndQualifiers typeAndQualifiers) {
List<BeanInfo> findTypeMatching(Type type) {
List<BeanInfo> resolved = new ArrayList<>();
//optimisation for the simple class case
Collection<BeanInfo> potentialBeans = type.kind() == CLASS ? beanDeployment.getBeansByType(type)
: beanDeployment.getBeans();
Collection<BeanInfo> potentialBeans = potentialBeans(type);
for (BeanInfo b : potentialBeans) {
if (Beans.matchesType(b, type)) {
resolved.add(b);
Expand All @@ -107,6 +104,13 @@ List<BeanInfo> findTypeMatching(Type type) {
return resolved.isEmpty() ? Collections.emptyList() : resolved;
}

Collection<BeanInfo> potentialBeans(Type type) {
if ((type.kind() == CLASS || type.kind() == PARAMETERIZED_TYPE) && !type.name().equals(DotNames.OBJECT)) {
return beanDeployment.getBeansByRawType(type.name());
}
return beanDeployment.getBeans();
}

boolean matches(Type requiredType, Type beanType) {
return matchesNoBoxing(Types.box(requiredType), Types.box(beanType));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public void testGetTypeClosure() throws IOException {
ParameterizedType fooType = t.asParameterizedType();
assertEquals("T", fooType.arguments().get(0).asTypeVariable().identifier());
assertEquals(DotNames.OBJECT, fooType.arguments().get(0).asTypeVariable().bounds().get(0).name());
assertTrue(Types.containsTypeVariable(fooType));
}
}
ClassInfo producerClass = index.getClassByName(producerName);
Expand Down

0 comments on commit c30379f

Please sign in to comment.