bazel-0003 + kicad-0002: build toolchain feature check + PCB zone filler O(Z²×L²); count 601→603
This commit is contained in:
parent
1d6a8b8ccd
commit
212d313185
292 changed files with 924 additions and 7 deletions
57
defects/bazel/patch/bazel-0003-feature-selection-hashset.md
Normal file
57
defects/bazel/patch/bazel-0003-feature-selection-hashset.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# bazel-0003: FeatureSelection ImmutableList.contains O(P×S×L) → O(P×S) with HashSet
|
||||
|
||||
## Classification
|
||||
|
||||
| Field | Value |
|
||||
|-------------|-------|
|
||||
| CWE | CWE-407 Inefficient Algorithmic Complexity |
|
||||
| Severity | MEDIUM |
|
||||
| Component | `src/main/java/com/google/devtools/build/lib/rules/cpp/FeatureSelection.java:159` |
|
||||
| Function | `FeatureSelection.run()` — provides-conflict check |
|
||||
| Hot path | Once per action type per C++ target in `computeFeatureConfiguration()` |
|
||||
| Status | PATCHED (unit test PASS) |
|
||||
|
||||
## Defect
|
||||
|
||||
`FeatureSelection.run()` iterates over `provides.keys()` (P unique provide-strings) and
|
||||
for each iterates `provides.get(provided)` (S selectables), calling
|
||||
`enabledActivatablesInOrder.contains(...)` — an O(L) scan of an `ImmutableList`:
|
||||
|
||||
```java
|
||||
// FeatureSelection.java:159
|
||||
ImmutableList<CrosstoolSelectable> enabledActivatablesInOrder = ...; // L entries
|
||||
|
||||
for (String provided : provides.keys()) { // P provide-strings
|
||||
for (CrosstoolSelectable selectable : provides.get(provided)) { // S selectables
|
||||
if (enabledActivatablesInOrder.contains( // O(L) linear scan
|
||||
selectableProvidingString)) {
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`ImmutableList.contains()` is O(L) — walks every element. With P=7, S=6, L=80:
|
||||
**~3,360 comparisons per call** vs ~42 with a HashSet (80×).
|
||||
|
||||
`computeFeatureConfiguration()` is called once per action type per target in C++ builds.
|
||||
Large monorepo builds with thousands of C++ targets hit this path repeatedly.
|
||||
|
||||
## Fix
|
||||
|
||||
Build a `HashSet<CrosstoolSelectable>` from `enabledActivatablesInOrder` once before the
|
||||
outer loop:
|
||||
|
||||
```java
|
||||
Set<CrosstoolSelectable> enabledSet = new HashSet<>(enabledActivatablesInOrder);
|
||||
|
||||
for (String provided : provides.keys()) {
|
||||
for (CrosstoolSelectable selectable : provides.get(provided)) {
|
||||
if (enabledSet.contains(selectableProvidingString)) { // O(1)
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Speedup: ~80× at realistic scale (L=80, P=7, S=6).
|
||||
Loading…
Add table
Add a link
Reference in a new issue