GC reduction: convertStarlarkArgumentsToJavaMethodArguments
- use ArrayList instead of ImmutableList.Builder
This reduces the number of copies by one, because
ImmutableList.Builder.build makes a copy, and toArray makes another
copy, whereas with ArrayList the first copy goes away (the second still
applies).
- use CompactHashSet instead of LinkedHashSet
- avoid creating a new Set if it's going to be empty
note that CompactHashSet actually _increases_ memory consumption for
empty sets, so we need to make sure that we don't do that
On a benchmark, this reduces memory allocation by this method by a
factor of more than 2.
PiperOrigin-RevId: 255959188
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index 55939a1..6949316 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -488,6 +488,7 @@
":skylarkinterface",
":util",
"//src/main/java/com/google/devtools/build/lib/cmdline",
+ "//src/main/java/com/google/devtools/build/lib/collect/compacthashset",
"//src/main/java/com/google/devtools/build/lib/collect/nestedset",
"//src/main/java/com/google/devtools/build/lib/concurrent",
"//src/main/java/com/google/devtools/build/lib/profiler",
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java
index c0ae74e..6875247 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java
@@ -22,8 +22,10 @@
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.collect.compacthashset.CompactHashSet;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkInterfaceUtils;
@@ -39,7 +41,6 @@
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -498,15 +499,16 @@
"struct field methods should be handled by DotExpression separately");
ImmutableList<ParamDescriptor> parameters = method.getParameters();
- ImmutableList.Builder<Object> builder =
- ImmutableList.builderWithExpectedSize(parameters.size() + EXTRA_ARGS_COUNT);
+ List<Object> builder = new ArrayList<>(parameters.size() + EXTRA_ARGS_COUNT);
boolean acceptsExtraArgs = method.isAcceptsExtraArgs();
boolean acceptsExtraKwargs = method.isAcceptsExtraKwargs();
int argIndex = 0;
// Process parameters specified in callable.parameters()
- Set<String> keys = new LinkedHashSet<>(kwargs.keySet());
+ // Many methods don't have any kwargs, so don't allocate a new hash set in that case.
+ Set<String> keys =
+ kwargs.isEmpty() ? ImmutableSet.of() : CompactHashSet.create(kwargs.keySet());
// Positional parameters are always enumerated before non-positional parameters,
// And default-valued positional parameters are always enumerated after other positional
// parameters. These invariants are validated by the SkylarkCallable annotation processor.
@@ -541,7 +543,7 @@
}
argIndex++;
} else { // No more positional arguments, or no more positional parameters.
- if (param.isNamed() && keys.remove(param.getName())) {
+ if (param.isNamed() && !keys.isEmpty() && keys.remove(param.getName())) {
// Param specified by keyword argument.
value = kwargs.get(param.getName());
if (!type.contains(value)) {
@@ -607,7 +609,7 @@
}
appendExtraInterpreterArgs(builder, method, this, getLocation(), environment);
- return builder.build().toArray();
+ return builder.toArray();
}
private EvalException unspecifiedParameterException(
@@ -701,9 +703,9 @@
*/
public static List<Object> extraInterpreterArgs(
MethodDescriptor method, @Nullable FuncallExpression ast, Location loc, Environment env) {
- ImmutableList.Builder<Object> builder = ImmutableList.builder();
+ List<Object> builder = new ArrayList<>();
appendExtraInterpreterArgs(builder, method, ast, loc, env);
- return builder.build();
+ return ImmutableList.copyOf(builder);
}
/**
@@ -714,7 +716,7 @@
* @see #extraInterpreterArgs(MethodDescriptor, FuncallExpression, Location, Environment)
*/
private static void appendExtraInterpreterArgs(
- ImmutableList.Builder<Object> builder,
+ List<Object> builder,
MethodDescriptor method,
@Nullable FuncallExpression ast,
Location loc,