Skip to content

Commit fa6b1b7

Browse files
brandjoncopybara-github
authored andcommitted
Reverse a RAM regression introduced by bazelbuild@7e53880
That CL factored some content of `Rule` into a new base class, `RuleOrMacroInstance`. In doing so, it added two new fields to `Rule` instances, causing a 1% RAM regression on a large `query` invocation. This CL eliminates the two extra fields. `attrCount`, the number of attributes in the rule or macro's schema (not to be confused with the number of attributes actually stored on the instance, which may change after freezing/compacting), can be obtained from the schema via the subclass's `ruleClass` or `macroClass` field without storing it as an additional field on the base class. We have to take care not to do this retrieval of the subclass field while executing the super constructor (i.e. before the subclass field is initialized). That's solved by threading `attrCount` into `bitSetSize` as a parameter. (A prior draft of this CL went through some indirect initialization logic whereby the super constructor called an abstract method to initialized the subclass field. Thanks to arostovtsev@ for pointing out that this was unnecessary.) The second field, `packageDeclarations`, is replaced by an abstract getter that already exists on `Rule` and which is added to `MacroInstance` in this CL. It's probably not really needed on `MacroInstance`, but we can eliminate that latter; the cost of an extra field on a macro is nothing like the cost of an extra field on a rule. PiperOrigin-RevId: 740793903 Change-Id: Iec65f20ff459e33c3961b16d9d51d0d4a22f0e00
1 parent 8587f74 commit fa6b1b7

File tree

3 files changed

+24
-18
lines changed

3 files changed

+24
-18
lines changed

src/main/java/com/google/devtools/build/lib/packages/MacroInstance.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import java.util.List;
2828
import java.util.function.Consumer;
2929
import javax.annotation.Nullable;
30-
import net.starlark.java.eval.EvalException;
3130

3231
/**
3332
* Represents a use of a symbolic macro in a package.
@@ -45,6 +44,11 @@ public final class MacroInstance extends RuleOrMacroInstance {
4544
// single field of type Object, and walk up the parent hierarchy to answer getPackage() queries.
4645
private final Package.Metadata packageMetadata;
4746

47+
// TODO(bazel-team): This is only needed for RuleOrMacroInstance#getPackageDeclarations(), which
48+
// is used by the attribute mapper logic. That might only be needed for rules rather than macros.
49+
// Consider removing it and pushing getPackageDeclarations() down to Rule.
50+
private final Package.Declarations packageDeclarations;
51+
4852
@Nullable private final MacroInstance parent;
4953

5054
private final MacroClass macroClass;
@@ -57,9 +61,6 @@ public final class MacroInstance extends RuleOrMacroInstance {
5761
* <p>{@code sameNameDepth} is the number of macro instances that this one is inside of that share
5862
* its name. For most instances it is 1, but for the main submacro of a parent macro it is one
5963
* more than the parent's depth.
60-
*
61-
* @throws EvalException if there's a problem with the attribute values (currently, only thrown if
62-
* the {@code visibility} value is invalid)
6364
*/
6465
// TODO: #19922 - Better encapsulate the invariant around attrValues, by either transitioning to
6566
// storing internal-typed values (the way Rules do) instead of Starlark-typed values, or else just
@@ -71,8 +72,9 @@ public MacroInstance(
7172
MacroClass macroClass,
7273
Label label,
7374
int sameNameDepth) {
74-
super(label, packageDeclarations, macroClass.getAttributeProvider().getAttributeCount());
75+
super(label, macroClass.getAttributeProvider().getAttributeCount());
7576
this.packageMetadata = packageMetadata;
77+
this.packageDeclarations = packageDeclarations;
7678
this.parent = parent;
7779
this.macroClass = macroClass;
7880
Preconditions.checkArgument(sameNameDepth > 0);
@@ -84,6 +86,11 @@ public Package.Metadata getPackageMetadata() {
8486
return packageMetadata;
8587
}
8688

89+
@Override
90+
Declarations getPackageDeclarations() {
91+
return packageDeclarations;
92+
}
93+
8794
/**
8895
* Returns the macro instance that instantiated this one, or null if this was created directly
8996
* during BUILD evaluation.

src/main/java/com/google/devtools/build/lib/packages/Rule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public class Rule extends RuleOrMacroInstance implements Target {
112112
RuleClass ruleClass,
113113
Location location,
114114
@Nullable CallStack.Node interiorCallStack) {
115-
super(label, pkg.getDeclarations(), ruleClass.getAttributeProvider().getAttributeCount());
115+
super(label, ruleClass.getAttributeProvider().getAttributeCount());
116116
this.pkg = checkNotNull(pkg);
117117
this.ruleClass = checkNotNull(ruleClass);
118118
this.location = checkNotNull(location);

src/main/java/com/google/devtools/build/lib/packages/RuleOrMacroInstance.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ public abstract class RuleOrMacroInstance implements DependencyFilter.AttributeI
4343
static final String GENERATOR_LOCATION = "generator_location";
4444

4545
private static final int ATTR_SIZE_THRESHOLD = 126;
46-
private final int attrCount;
47-
48-
@Nullable private final Declarations packageDeclarations;
4946

5047
/**
5148
* For {@link Rule}s, the length of this instance's generator name if it is a prefix of its name,
@@ -68,12 +65,10 @@ public abstract class RuleOrMacroInstance implements DependencyFilter.AttributeI
6865
*/
6966
int generatorNamePrefixLength = 0;
7067

71-
RuleOrMacroInstance(Label label, Declarations packageDeclarations, int attrCount) {
68+
RuleOrMacroInstance(Label label, int attrCount) {
7269
this.label = checkNotNull(label);
73-
this.packageDeclarations = packageDeclarations;
7470
this.attrValues = new Object[attrCount];
75-
this.attrCount = attrCount;
76-
this.attrBytes = new byte[bitSetSize()];
71+
this.attrBytes = new byte[bitSetSize(attrCount)];
7772
}
7873

7974
/**
@@ -260,6 +255,7 @@ Object getAttrWithIndex(int attrIndex) {
260255
*/
261256
@Nullable
262257
Object getAttrIfStored(int attrIndex) {
258+
int attrCount = getAttributeProvider().getAttributeCount();
263259
checkPositionIndex(attrIndex, attrCount - 1);
264260
return switch (getAttrState()) {
265261
case MUTABLE -> attrValues[attrIndex];
@@ -271,7 +267,7 @@ Object getAttrIfStored(int attrIndex) {
271267
if (attrBytes.length == 0) {
272268
yield null;
273269
}
274-
int bitSetSize = bitSetSize();
270+
int bitSetSize = bitSetSize(attrCount);
275271
int index = binarySearchAttrBytes(bitSetSize, attrIndex, 0xff);
276272
yield index < 0 ? null : attrValues[index - bitSetSize];
277273
}
@@ -408,7 +404,7 @@ void freeze() {
408404
indicesToStore.set(i);
409405
}
410406

411-
if (attrCount < ATTR_SIZE_THRESHOLD) {
407+
if (getAttributeProvider().getAttributeCount() < ATTR_SIZE_THRESHOLD) {
412408
freezeSmall(indicesToStore);
413409
} else {
414410
freezeLarge(indicesToStore);
@@ -464,15 +460,16 @@ enum AttrState {
464460

465461
AttrState getAttrState() {
466462
// This check works because the name attribute is never stored, so the compact representation
467-
// of attrValues will always have length < attrCount.
463+
// of attrValues will always have length < attr count.
464+
int attrCount = getAttributeProvider().getAttributeCount();
468465
if (attrValues.length == attrCount) {
469466
return AttrState.MUTABLE;
470467
}
471468
return attrCount < ATTR_SIZE_THRESHOLD ? AttrState.FROZEN_SMALL : AttrState.FROZEN_LARGE;
472469
}
473470

474471
/** Calculates the number of bytes necessary to have an explicit bit for each attribute. */
475-
private int bitSetSize() {
472+
private static int bitSetSize(int attrCount) {
476473
// ceil(attrCount / 8)
477474
return (attrCount + 7) / 8;
478475
}
@@ -548,9 +545,11 @@ public List<Label> getVisibilityDeclaredLabels() {
548545
return rawLabels != null ? rawLabels : getDefaultVisibility().getDeclaredLabels();
549546
}
550547

548+
abstract Declarations getPackageDeclarations();
549+
551550
@Nullable
552551
public PackageArgs getPackageArgs() {
553-
return packageDeclarations.getPackageArgs();
552+
return getPackageDeclarations().getPackageArgs();
554553
}
555554

556555
abstract void reportError(String message, EventHandler eventHandler);

0 commit comments

Comments
 (0)