Skip to content

Commit b5e080a

Browse files
authored
Improve performance for transitive dependency checks (#1381)
`TransitiveDependencyCondition` internally calls `contains()` recursively on the collection of all objects to be tested. If this collection is a large list and there are enough recursive calls to `getDirectDependencyTargetsOutsideOfAnalyzedClasses()` this results in a heavy performance impact. On a reasonable large project a single test using that condition may take minutes to complete. Here is a 30 seconds FlameGraph taken while an transitive check was running for > 2 minutes: ![FlameGraph_30s](https://github.com/user-attachments/assets/fe4096b9-c6f7-4d2f-a448-1bf17f5802b5) Based on the samples, the CPU hangs in [this filter lamdba](https://github.com/TNG/ArchUnit/blob/main/archunit/src/main/java/com/tngtech/archunit/lang/conditions/TransitiveDependencyCondition.java#L91) for > 86% of the time: - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (47,247,323 samples, 0.03%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (44,447,761 samples, 0.03%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (10,837,882,731 samples, 7.32%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (13,262,127,759 samples, 8.96%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (12,668,650,362 samples, 8.56%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (15,368,403,186 samples, 10.38%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (46,224,364 samples, 0.03%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (47,314,101 samples, 0.03%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (18,048,208,277 samples, 12.19%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (13,405,921,387 samples, 9.06%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (93,152,524 samples, 0.06%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (3,244,023,882 samples, 2.19%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (919,865,902 samples, 0.62%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (6,438,577,874 samples, 4.35%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (6,760,263,856 samples, 4.57%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (7,031,313,250 samples, 4.75%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (7,723,048,585 samples, 5.22%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (11,918,050,716 samples, 8.05%) - TransitiveDependencyCondition$$Lambda$553.0x000000080121ca88:::test (46,026,822 samples, 0.03%) So, converting the given list to a Set with much better `contains()` performance fixes this issue.
2 parents 54fae8d + 9c6adcb commit b5e080a

File tree

1 file changed

+3
-2
lines changed

1 file changed

+3
-2
lines changed

archunit/src/main/java/com/tngtech/archunit/lang/conditions/TransitiveDependencyCondition.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Set;
2222

2323
import com.google.common.collect.ImmutableList;
24+
import com.google.common.collect.ImmutableSet;
2425
import com.tngtech.archunit.PublicAPI;
2526
import com.tngtech.archunit.base.DescribedPredicate;
2627
import com.tngtech.archunit.core.domain.JavaClass;
@@ -41,7 +42,7 @@ public final class TransitiveDependencyCondition extends ArchCondition<JavaClass
4142

4243
private final DescribedPredicate<? super JavaClass> conditionPredicate;
4344
private final TransitiveDependencyPath transitiveDependencyPath = new TransitiveDependencyPath();
44-
private Collection<JavaClass> allClasses;
45+
private Set<JavaClass> allClasses;
4546

4647
public TransitiveDependencyCondition(DescribedPredicate<? super JavaClass> conditionPredicate) {
4748
super("transitively depend on classes that " + conditionPredicate.getDescription());
@@ -51,7 +52,7 @@ public TransitiveDependencyCondition(DescribedPredicate<? super JavaClass> condi
5152

5253
@Override
5354
public void init(Collection<JavaClass> allObjectsToTest) {
54-
this.allClasses = allObjectsToTest;
55+
this.allClasses = ImmutableSet.copyOf(allObjectsToTest);
5556
}
5657

5758
@Override

0 commit comments

Comments
 (0)