From 35f5a09b0fe6c25cc89266685e851e872d430a67 Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Mon, 15 Aug 2022 17:08:56 +0200 Subject: [PATCH] Optimize ArcDevConsoleProcessor.buildDependencyGraph() - resolves #27281 --- .../devconsole/ArcDevConsoleProcessor.java | 93 ++++++++++++------- .../io/quarkus/arc/processor/BeanInfo.java | 4 + 2 files changed, 66 insertions(+), 31 deletions(-) diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/ArcDevConsoleProcessor.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/ArcDevConsoleProcessor.java index 5e4f85f8a1d0c..743663e82edcf 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/ArcDevConsoleProcessor.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/ArcDevConsoleProcessor.java @@ -1,7 +1,9 @@ package io.quarkus.arc.deployment.devconsole; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -134,9 +136,24 @@ public DevConsoleTemplateInfoBuildItem collectBeanInfo(ValidationPhaseBuildItem // Build dependency graphs BeanResolver resolver = validationPhaseBuildItem.getBeanResolver(); - for (BeanInfo bean : validationContext.beans()) { + Collection beans = validationContext.get(BuildExtension.Key.BEANS); + Map> directDependents = new HashMap<>(); + List allInjectionPoints = new ArrayList<>(); + Map> declaringToProducers = validationContext.beans().producers() + .collect(Collectors.groupingBy(BeanInfo::getDeclaringBean)); + for (BeanInfo b : beans) { + if (b.hasInjectionPoint()) { + for (InjectionPointInfo ip : b.getAllInjectionPoints()) { + if (ip.getTargetBean().isPresent()) { + allInjectionPoints.add(ip); + } + } + } + } + for (BeanInfo bean : beans) { beanInfos.addDependencyGraph(bean.getIdentifier(), - buildDependencyGraph(bean, validationContext, resolver, beanInfos)); + buildDependencyGraph(bean, validationContext, resolver, beanInfos, allInjectionPoints, declaringToProducers, + directDependents)); } beanInfos.sort(); @@ -154,14 +171,14 @@ private boolean isAdditionalBeanDefiningAnnotationOn(ClassInfo beanClass, } DependencyGraph buildDependencyGraph(BeanInfo bean, ValidationContext validationContext, BeanResolver resolver, - DevBeanInfos devBeanInfos) { + DevBeanInfos devBeanInfos, List allInjectionPoints, + Map> declaringToProducers, + Map> directDependents) { Set nodes = new HashSet<>(); - Collection beans = validationContext.get(BuildExtension.Key.BEANS); Set links = new HashSet<>(); - Map> declaringToProducers = validationContext.beans().producers() - .collect(Collectors.groupingBy(BeanInfo::getDeclaringBean)); addNodesDependencies(bean, nodes, links, bean, devBeanInfos); - addNodesDependents(bean, nodes, links, bean, beans, declaringToProducers, resolver, devBeanInfos); + addNodesDependents(bean, nodes, links, bean, allInjectionPoints, declaringToProducers, resolver, devBeanInfos, + directDependents); return new DependencyGraph(nodes, links); } @@ -183,38 +200,52 @@ void addNodesDependencies(BeanInfo root, Set nodes, Set links } } - void addNodesDependents(BeanInfo root, Set nodes, Set links, BeanInfo bean, Collection beans, - Map> declaringToProducers, BeanResolver resolver, DevBeanInfos devBeanInfos) { - for (BeanInfo dependent : beans) { - if (!bean.equals(dependent)) { - for (InjectionPointInfo injectionPoint : dependent.getAllInjectionPoints()) { - Link link = null; - if (injectionPoint.isProgrammaticLookup()) { - if (resolver.matches(bean, - injectionPoint.getType().asParameterizedType().arguments().get(0), - injectionPoint.getRequiredQualifiers())) { - link = Link.lookup(dependent.getIdentifier(), bean.getIdentifier()); - } - } else if (bean.equals(injectionPoint.getResolvedBean())) { - link = Link.dependent(root.equals(bean), dependent.getIdentifier(), bean.getIdentifier()); - } - if (link != null) { - links.add(link); - if (nodes.add(devBeanInfos.getBean(dependent.getIdentifier()))) { - // add transient dependents - addNodesDependents(root, nodes, links, dependent, beans, declaringToProducers, resolver, - devBeanInfos); - } + void addNodesDependents(BeanInfo root, Set nodes, Set links, BeanInfo bean, + List injectionPoints, Map> declaringToProducers, BeanResolver resolver, + DevBeanInfos devBeanInfos, Map> directDependents) { + List direct = directDependents.get(bean); + if (direct == null) { + direct = new ArrayList<>(); + for (InjectionPointInfo injectionPoint : injectionPoints) { + BeanInfo dependent = injectionPoint.getTargetBean().get(); + if (dependent.equals(bean)) { + continue; + } + BeanInfo resolved = injectionPoint.getResolvedBean(); + if (resolved == null) { + if (injectionPoint.isProgrammaticLookup() && resolver.matches(bean, + injectionPoint.getType().asParameterizedType().arguments().get(0), + injectionPoint.getRequiredQualifiers())) { + direct.add(injectionPoint); } + } else if (bean.equals(resolved)) { + direct.add(injectionPoint); } } + directDependents.put(bean, direct); } + for (InjectionPointInfo ip : direct) { + BeanInfo dependent = ip.getTargetBean().get(); + Link link; + if (ip.getResolvedBean() == null) { + link = Link.lookup(dependent.getIdentifier(), bean.getIdentifier()); + } else { + link = Link.dependent(root.equals(bean), dependent.getIdentifier(), bean.getIdentifier()); + } + links.add(link); + if (nodes.add(devBeanInfos.getBean(dependent.getIdentifier()))) { + // add transient dependents + addNodesDependents(root, nodes, links, dependent, injectionPoints, declaringToProducers, resolver, + devBeanInfos, directDependents); + } + } + for (BeanInfo producer : declaringToProducers.getOrDefault(bean, Collections.emptyList())) { links.add(Link.producer(producer.getIdentifier(), bean.getIdentifier())); if (nodes.add(devBeanInfos.getBean(producer.getIdentifier()))) { // add transient dependents - addNodesDependents(root, nodes, links, producer, beans, declaringToProducers, resolver, - devBeanInfos); + addNodesDependents(root, nodes, links, producer, injectionPoints, declaringToProducers, resolver, + devBeanInfos, directDependents); } } } diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java index 502024565537c..20173365f9615 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java @@ -262,6 +262,10 @@ List getInjections() { return injections; } + public boolean hasInjectionPoint() { + return !injections.isEmpty(); + } + public List getAllInjectionPoints() { if (injections.isEmpty()) { return Collections.emptyList();