Skip to content

Commit 43555aa

Browse files
sellophaneGoogler
and
Googler
authored
Separate BEP analysis and parsing (#7355)
since the former is not needed in the query sync mode. - Do not flatten the graph while processing events - Instead collect data in a suitable for further processing form in an instance of `OutputGroupTargetConfigFileSetMap`. Bug: 327638725 Test: existing Change-Id: I41bfb406f2f0432d825f7e41b1bf350f07bb6ed5 AOSP: 22b93c09bf3b9cf161fe86246d7a982f26717ac6 Co-authored-by: Googler <[email protected]>
1 parent ba6490e commit 43555aa

File tree

1 file changed

+112
-46
lines changed
  • base/src/com/google/idea/blaze/base/command/buildresult/bepparser

1 file changed

+112
-46
lines changed

base/src/com/google/idea/blaze/base/command/buildresult/bepparser/BepParser.java

+112-46
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.google.idea.blaze.base.command.buildresult.bepparser;
1717

18+
import static com.google.common.base.Preconditions.checkNotNull;
1819
import static com.google.common.collect.ImmutableList.toImmutableList;
1920
import static com.google.common.collect.ImmutableMap.toImmutableMap;
2021

@@ -26,6 +27,7 @@
2627
import com.google.common.collect.ImmutableSetMultimap;
2728
import com.google.common.collect.Interner;
2829
import com.google.common.collect.Interners;
30+
import com.google.common.collect.Maps;
2931
import com.google.common.collect.Queues;
3032
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
3133
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.WorkspaceStatus.Item;
@@ -38,13 +40,12 @@
3840
import java.util.HashMap;
3941
import java.util.HashSet;
4042
import java.util.LinkedHashMap;
41-
import java.util.List;
4243
import java.util.Map;
4344
import java.util.Objects;
4445
import java.util.Queue;
4546
import java.util.Set;
4647
import java.util.concurrent.Semaphore;
47-
import java.util.stream.Collectors;
48+
import java.util.stream.Stream;
4849
import javax.annotation.Nullable;
4950

5051
public final class BepParser {
@@ -63,6 +64,78 @@ public static ParsedBepOutput parseBepArtifacts(BuildEventStreamProvider stream)
6364
return parseBepArtifacts(stream, null);
6465
}
6566

67+
/**
68+
* A record of the top level file sets output by the given {@link #outputGroup}, {@link #target} and {@link #config}.
69+
*/
70+
private record OutputGroupTargetConfigFileSets(String outputGroup, String target, String config, ImmutableList<String> fileSetNames){}
71+
72+
/**
73+
* A data structure allowing to associate file set names with output group, targets and configs and allowing to retrieve them efficiently
74+
* at each level of the hierarchy.
75+
*/
76+
private static class OutputGroupTargetConfigFileSetMap {
77+
private final Map<String, Map<String, Map<String, ImmutableList<String>>>> data = new LinkedHashMap<>();
78+
79+
private Map<String, Map<String, ImmutableList<String>>> getOutputGroup(String outputGroup) {
80+
return data.computeIfAbsent(outputGroup, it -> new LinkedHashMap<>());
81+
}
82+
83+
private Map<String, ImmutableList<String>> getOutputGroupTarget(String outputGroup, String target) {
84+
return getOutputGroup(outputGroup).computeIfAbsent(target, it -> new LinkedHashMap<>());
85+
}
86+
87+
private ImmutableList<String> getOutputGroupTargetConfig(String outputGroup, String target, String config) {
88+
final var result = getOutputGroupTarget(outputGroup, target).get(config);
89+
return result != null ? result : ImmutableList.of();
90+
}
91+
92+
public void setOutputGroupTargetConfig(String outputGroup, String target, String config, ImmutableList<String> fileSetNames) {
93+
final var previous = getOutputGroupTarget(outputGroup, target).put(config, fileSetNames);
94+
if (previous != null){
95+
throw new IllegalStateException(outputGroup + ":" + target + ":" + config + " already present");
96+
}
97+
}
98+
99+
public Stream<OutputGroupTargetConfigFileSets> fileSetStream() {
100+
return data.entrySet().stream().flatMap(
101+
outputGroup ->
102+
outputGroup.getValue().entrySet().stream().flatMap(
103+
target ->
104+
target.getValue().entrySet().stream().map(
105+
config ->
106+
new OutputGroupTargetConfigFileSets(outputGroup.getKey(), target.getKey(),
107+
config.getKey(), config.getValue()))));
108+
}
109+
110+
public Stream<OutputGroupTargetConfigFileSets> outputGroupFileSetStream(String outputGroup) {
111+
final var outputGroupData = data.get(outputGroup);
112+
if (outputGroupData == null) {
113+
return Stream.empty();
114+
}
115+
return outputGroupData.entrySet().stream().flatMap(
116+
target ->
117+
target.getValue().entrySet().stream().map(
118+
config ->
119+
new OutputGroupTargetConfigFileSets(outputGroup, target.getKey(),
120+
config.getKey(), config.getValue())));
121+
}
122+
123+
public Stream<OutputGroupTargetConfigFileSets> outputGroupTargetFileSetStream(String outputGroup, String target) {
124+
final var outputGroupData = data.get(outputGroup);
125+
if (outputGroupData == null) {
126+
return Stream.empty();
127+
}
128+
final var outputGroupTargetData = outputGroupData.get(target);
129+
if (outputGroupTargetData == null) {
130+
return Stream.empty();
131+
}
132+
return outputGroupTargetData.entrySet().stream().map(
133+
config ->
134+
new OutputGroupTargetConfigFileSets(outputGroup, target,
135+
config.getKey(), config.getValue()));
136+
}
137+
}
138+
66139
/**
67140
* Parses BEP events into {@link ParsedBepOutput}. String references in {@link BuildEventStreamProtos.NamedSetOfFiles}
68141
* are interned to conserve memory.
@@ -71,20 +144,17 @@ public static ParsedBepOutput parseBepArtifacts(BuildEventStreamProvider stream)
71144
* shards running in parallel, so a {@link Interner} is used to share references.
72145
*/
73146
public static ParsedBepOutput parseBepArtifacts(
74-
BuildEventStreamProvider stream, @Nullable Interner<String> interner)
147+
BuildEventStreamProvider stream, @Nullable Interner<String> nullableInterner)
75148
throws BuildEventStreamProvider.BuildEventStreamException {
76149
final var semaphore = ApplicationManager.getApplication().getService(BepParserSemaphore.class);
77150
semaphore.start();
78151
try {
79-
if (interner == null) {
80-
interner = Interners.newStrongInterner();
81-
}
152+
final Interner<String> interner = nullableInterner == null ? Interners.newStrongInterner() : nullableInterner;
82153

83154
BuildEventStreamProtos.BuildEvent event;
84155
Map<String, String> configIdToMnemonic = new HashMap<>();
85-
Set<String> topLevelFileSets = new HashSet<>();
86-
Map<String, FileSetBuilder> fileSets = new LinkedHashMap<>();
87-
ImmutableSetMultimap.Builder<String, String> targetToFileSets = ImmutableSetMultimap.builder();
156+
Map<String, BuildEventStreamProtos.NamedSetOfFiles> fileSets = new LinkedHashMap<>();
157+
final var data = new OutputGroupTargetConfigFileSetMap();
88158
ImmutableSet.Builder<String> targetsWithErrors = ImmutableSet.builder();
89159
String localExecRoot = null;
90160
String buildId = null;
@@ -109,10 +179,7 @@ public static ParsedBepOutput parseBepArtifacts(
109179
continue;
110180
case NAMED_SET:
111181
BuildEventStreamProtos.NamedSetOfFiles namedSet = internNamedSet(event.getNamedSetOfFiles(), interner);
112-
fileSets.compute(
113-
event.getId().getNamedSet().getId(),
114-
(k, v) ->
115-
v != null ? v.setNamedSet(namedSet) : new FileSetBuilder().setNamedSet(namedSet));
182+
fileSets.put(interner.intern(event.getId().getNamedSet().getId()), namedSet);
116183
continue;
117184
case ACTION_COMPLETED:
118185
Preconditions.checkState(event.hasAction());
@@ -124,26 +191,10 @@ public static ParsedBepOutput parseBepArtifacts(
124191
String label = event.getId().getTargetCompleted().getLabel();
125192
String configId = event.getId().getTargetCompleted().getConfiguration().getId();
126193

127-
event
128-
.getCompleted()
129-
.getOutputGroupList()
130-
.forEach(
131-
o -> {
132-
List<String> sets = getFileSets(o);
133-
targetToFileSets.putAll(label, sets);
134-
topLevelFileSets.addAll(sets);
135-
for (String id : sets) {
136-
fileSets.compute(
137-
id,
138-
(k, v) -> {
139-
FileSetBuilder builder = (v != null) ? v : new FileSetBuilder();
140-
return builder
141-
.setConfigId(configId)
142-
.addOutputGroups(ImmutableSet.of(o.getName()))
143-
.addTargets(ImmutableSet.of(label));
144-
});
145-
}
146-
});
194+
for (BuildEventStreamProtos.OutputGroup o : event.getCompleted().getOutputGroupList()) {
195+
final var fileSetNames = getFileSets(o, interner);
196+
data.setOutputGroupTargetConfig(interner.intern(o.getName()), interner.intern(label), interner.intern(configId), fileSetNames);
197+
}
147198
continue;
148199
case STARTED:
149200
buildId = Strings.emptyToNull(event.getStarted().getUuid());
@@ -162,13 +213,15 @@ public static ParsedBepOutput parseBepArtifacts(
162213
}
163214
ImmutableMap<String, ParsedBepOutput.FileSet> filesMap =
164215
fillInTransitiveFileSetData(
165-
fileSets, topLevelFileSets, configIdToMnemonic, startTimeMillis);
216+
fileSets, data, configIdToMnemonic, startTimeMillis);
166217
return new ParsedBepOutput(
167218
buildId,
168219
localExecRoot,
169220
workspaceStatus,
170221
filesMap,
171-
targetToFileSets.build(),
222+
data.fileSetStream()
223+
.collect(ImmutableSetMultimap.flatteningToImmutableSetMultimap(OutputGroupTargetConfigFileSets::target,
224+
it -> it.fileSetNames().stream())),
172225
startTimeMillis,
173226
buildResult,
174227
stream.getBytesConsumed(),
@@ -179,21 +232,34 @@ public static ParsedBepOutput parseBepArtifacts(
179232
}
180233
}
181234

182-
private static List<String> getFileSets(BuildEventStreamProtos.OutputGroup group) {
235+
private static ImmutableList<String> getFileSets(BuildEventStreamProtos.OutputGroup group, Interner<String> interner) {
183236
return group.getFileSetsList().stream()
184-
.map(BuildEventStreamProtos.BuildEventId.NamedSetOfFilesId::getId)
185-
.collect(Collectors.toList());
237+
.map(namedSetOfFilesId -> interner.intern(namedSetOfFilesId.getId()))
238+
.collect(toImmutableList());
186239
}
187240

188241
/**
189242
* Only top-level targets have configuration mnemonic, producing target, and output group data
190243
* explicitly provided in BEP. This method fills in that data for the transitive closure.
191244
*/
192245
private static ImmutableMap<String, ParsedBepOutput.FileSet> fillInTransitiveFileSetData(
193-
Map<String, FileSetBuilder> fileSets,
194-
Set<String> topLevelFileSets,
246+
Map<String, BuildEventStreamProtos.NamedSetOfFiles> namedFileSets,
247+
OutputGroupTargetConfigFileSetMap data,
195248
Map<String, String> configIdToMnemonic,
196249
long startTimeMillis) {
250+
Map<String, FileSetBuilder> fileSets =
251+
ImmutableMap.copyOf(
252+
Maps.transformValues(namedFileSets, it -> new FileSetBuilder().setNamedSet(it)));
253+
Set<String> topLevelFileSets = new HashSet<>();
254+
data.fileSetStream().forEach(entry -> {
255+
entry.fileSetNames().forEach(fileSetName -> {
256+
final var fileSet = checkNotNull(fileSets.get(fileSetName));
257+
fileSet.setConfigId(entry.config());
258+
fileSet.addOutputGroup(entry.outputGroup());
259+
fileSet.addTarget(entry.target());
260+
topLevelFileSets.add(fileSetName);
261+
});
262+
});
197263
Queue<String> toVisit = Queues.newArrayDeque(topLevelFileSets);
198264
Set<String> visited = new HashSet<>(topLevelFileSets);
199265
while (!toVisit.isEmpty()) {
@@ -244,10 +310,10 @@ private static BuildEventStreamProtos.NamedSetOfFiles internNamedSet(
244310
.addAllPathPrefix(
245311
file.getPathPrefixList().stream()
246312
.map(interner::intern)
247-
.collect(Collectors.toUnmodifiableList()));
313+
.collect(toImmutableList()));
248314
return builder.build();
249315
})
250-
.collect(Collectors.toUnmodifiableList()))
316+
.collect(toImmutableList()))
251317
.build();
252318
}
253319

@@ -302,14 +368,14 @@ FileSetBuilder setConfigId(String configId) {
302368
}
303369

304370
@CanIgnoreReturnValue
305-
FileSetBuilder addOutputGroups(Set<String> outputGroups) {
306-
this.outputGroups.addAll(outputGroups);
371+
FileSetBuilder addOutputGroup(String outputGroup) {
372+
this.outputGroups.add(outputGroup);
307373
return this;
308374
}
309375

310376
@CanIgnoreReturnValue
311-
FileSetBuilder addTargets(Set<String> targets) {
312-
this.targets.addAll(targets);
377+
FileSetBuilder addTarget(String target) {
378+
this.targets.add(target);
313379
return this;
314380
}
315381

0 commit comments

Comments
 (0)