Skip to content

Commit 93191f3

Browse files
authored
Merge pull request #47633 from mkouba/issue-47596
ArC: optimize the generated dependency graphs for the Dev UI
2 parents 722368c + d26c932 commit 93191f3

File tree

6 files changed

+90
-11
lines changed

6 files changed

+90
-11
lines changed

extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcDevModeConfig.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,17 @@ public interface ArcDevModeConfig {
1515
boolean monitoringEnabled();
1616

1717
/**
18-
* If set to true then the dependency graphs are generated and available in the Dev UI.
18+
* If set to {@code true} then the dependency graphs are generated and available in the Dev UI. If set to {@code auto}
19+
* then the dependency graphs are generated if there's less than 1000 beans in the application. If set to {@code false} the
20+
* dependency graphs are not generated.
1921
*/
20-
@WithDefault("true")
21-
boolean generateDependencyGraphs();
22+
@WithDefault("auto")
23+
GenerateDependencyGraphs generateDependencyGraphs();
24+
25+
public enum GenerateDependencyGraphs {
26+
TRUE,
27+
FALSE,
28+
AUTO
29+
}
2230

2331
}

extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devui/ArcDevModeApiProcessor.java

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import java.util.Set;
1111
import java.util.stream.Collectors;
1212

13+
import org.jboss.logging.Logger;
14+
1315
import io.quarkus.arc.deployment.ArcConfig;
1416
import io.quarkus.arc.deployment.CompletedApplicationClassPredicateBuildItem;
1517
import io.quarkus.arc.deployment.ValidationPhaseBuildItem;
@@ -29,6 +31,19 @@
2931

3032
public class ArcDevModeApiProcessor {
3133

34+
private static final Logger LOG = Logger.getLogger(ArcDevModeApiProcessor.class);
35+
36+
/**
37+
* Do not generate dependency graphs for apps with more than N beans
38+
*/
39+
private static final int DEPENCENY_GRAPH_BEANS_LIMIT = 1000;
40+
41+
/**
42+
* If a dependency graph exceeds the limit then we apply the {@link DevBeanInfos#MAX_DEPENDENCY_LEVEL} and if still exceeds
43+
* the limit it's skipped completely, i.e. dependency graph is not available
44+
*/
45+
private static final int DEPENCENY_GRAPH_NODES_LIMIT = 30;
46+
3247
@BuildStep(onlyIf = IsDevelopment.class)
3348
public void collectBeanInfo(ArcConfig config, ValidationPhaseBuildItem validationPhaseBuildItem,
3449
CompletedApplicationClassPredicateBuildItem predicate,
@@ -65,7 +80,7 @@ public void collectBeanInfo(ArcConfig config, ValidationPhaseBuildItem validatio
6580

6681
// Build dependency graphs
6782
Map<String, List<String>> beanDependenciesMap = new HashMap<>();
68-
if (config.devMode().generateDependencyGraphs()) {
83+
if (generateDependencyGraphs(config, beanInfos)) {
6984
BeanResolver resolver = validationPhaseBuildItem.getBeanResolver();
7085
Collection<BeanInfo> beans = validationContext.get(BuildExtension.Key.BEANS);
7186
Map<BeanInfo, List<InjectionPointInfo>> directDependents = new HashMap<>();
@@ -85,11 +100,27 @@ public void collectBeanInfo(ArcConfig config, ValidationPhaseBuildItem validatio
85100
DependencyGraph dependencyGraph = buildDependencyGraph(bean, validationContext, resolver, beanInfos,
86101
allInjectionPoints, declaringToProducers,
87102
directDependents);
103+
if (dependencyGraph.links.isEmpty()) {
104+
// Skip the graph if no links exist
105+
continue;
106+
}
107+
if (dependencyGraph.nodes.size() > DEPENCENY_GRAPH_NODES_LIMIT) {
108+
DependencyGraph visibleGraph = dependencyGraph.forLevel(DevBeanInfos.DEFAULT_MAX_DEPENDENCY_LEVEL);
109+
if (visibleGraph.nodes.size() > DEPENCENY_GRAPH_NODES_LIMIT) {
110+
LOG.debugf("Skip dependency graph for %s - too many visible nodes: %s", bean,
111+
visibleGraph.nodes.size());
112+
continue;
113+
} else {
114+
LOG.debugf("Dependency graph for %s was reduced to visible nodes: %s", bean,
115+
dependencyGraph.nodes.size());
116+
dependencyGraph = visibleGraph;
117+
}
118+
}
88119
beanInfos.addDependencyGraph(bean.getIdentifier(), dependencyGraph);
89120
// id -> [dep1Id, dep2Id]
90121
beanDependenciesMap.put(bean.getIdentifier(),
91122
dependencyGraph.filterLinks(link -> link.type.equals("directDependency")).nodes.stream()
92-
.map(DevBeanInfo::getId).filter(id -> !id.equals(bean.getIdentifier()))
123+
.map(Node::getId).filter(id -> !id.equals(bean.getIdentifier()))
93124
.collect(Collectors.toList()));
94125
}
95126
}
@@ -111,7 +142,7 @@ DependencyGraph buildDependencyGraph(BeanInfo bean, ValidationContext validation
111142
addNodesDependencies(0, bean, nodes, links, bean, devBeanInfos);
112143
addNodesDependents(0, bean, nodes, links, bean, allInjectionPoints, declaringToProducers, resolver, devBeanInfos,
113144
directDependents);
114-
return new DependencyGraph(nodes, links);
145+
return new DependencyGraph(nodes.stream().map(Node::from).collect(Collectors.toSet()), links);
115146
}
116147

117148
private void addNodesDependencies(int level, BeanInfo root, Set<DevBeanInfo> nodes, Set<Link> links, BeanInfo bean,
@@ -184,4 +215,13 @@ private void addNodesDependents(int level, BeanInfo root, Set<DevBeanInfo> nodes
184215
}
185216
}
186217

218+
private boolean generateDependencyGraphs(ArcConfig config, DevBeanInfos beanInfos) {
219+
return switch (config.devMode().generateDependencyGraphs()) {
220+
case TRUE -> true;
221+
case FALSE -> false;
222+
case AUTO -> beanInfos.getBeans().size() < DEPENCENY_GRAPH_BEANS_LIMIT;
223+
default -> throw new IllegalArgumentException("Unexpected value: " + config.devMode().generateDependencyGraphs());
224+
};
225+
}
226+
187227
}

extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devui/DependencyGraph.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ public class DependencyGraph {
88

99
static final DependencyGraph EMPTY = new DependencyGraph(Set.of(), Set.of());
1010

11-
public final Set<DevBeanInfo> nodes;
11+
public final Set<Node> nodes;
1212
public final Set<Link> links;
1313
public final int maxLevel;
1414

15-
public DependencyGraph(Set<DevBeanInfo> nodes, Set<Link> links) {
15+
public DependencyGraph(Set<Node> nodes, Set<Link> links) {
1616
this.nodes = nodes;
1717
this.links = links;
1818
this.maxLevel = links.stream().mapToInt(l -> l.level).max().orElse(0);
@@ -25,7 +25,7 @@ DependencyGraph forLevel(int level) {
2525
DependencyGraph filterLinks(Predicate<Link> predicate) {
2626
// Filter out links first
2727
Set<Link> newLinks = new HashSet<>();
28-
Set<DevBeanInfo> newNodes = new HashSet<>();
28+
Set<Node> newNodes = new HashSet<>();
2929
Set<String> usedIds = new HashSet<>();
3030
for (Link link : links) {
3131
if (predicate.test(link)) {
@@ -35,7 +35,7 @@ DependencyGraph filterLinks(Predicate<Link> predicate) {
3535
}
3636
}
3737
// Now keep only nodes for which a link exists...
38-
for (DevBeanInfo node : nodes) {
38+
for (Node node : nodes) {
3939
if (usedIds.contains(node.getId())) {
4040
newNodes.add(node);
4141
}

extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devui/DevBeanInfos.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public DevInterceptorInfo getInterceptor(String id) {
9090
}
9191

9292
public DependencyGraph getDependencyGraph(String beanId) {
93+
// Note that MAX_DEPENDENCY_LEVEL is not implemented in UI yet
9394
Integer maxLevel = DevConsoleManager.getGlobal(MAX_DEPENDENCY_LEVEL);
9495
if (maxLevel == null) {
9596
maxLevel = DEFAULT_MAX_DEPENDENCY_LEVEL;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.quarkus.arc.deployment.devui;
2+
3+
public class Node {
4+
5+
static Node from(DevBeanInfo beanInfo) {
6+
return new Node(beanInfo.getId(), beanInfo.getDescription(), beanInfo.getSimpleDescription());
7+
}
8+
9+
private final String id;
10+
private final String description;
11+
private final String simpleDescription;
12+
13+
Node(String id, String description, String simpleDescription) {
14+
this.id = id;
15+
this.description = description;
16+
this.simpleDescription = simpleDescription;
17+
}
18+
19+
public String getId() {
20+
return id;
21+
}
22+
23+
public String getDescription() {
24+
return description;
25+
}
26+
27+
public String getSimpleDescription() {
28+
return simpleDescription;
29+
}
30+
31+
}

extensions/arc/deployment/src/main/resources/dev-ui/qwc-arc-bean-graph.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ export class QwcArcBeanGraph extends LitElement {
9292
}else {
9393
newNode.category = catindex;
9494
}
95-
//console.log('Adding node: ' + newNode.name);
9695
return this._nodes.push(newNode) - 1;
9796
}
9897
return index;

0 commit comments

Comments
 (0)