diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryMapping.java b/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryMapping.java index 0246c930171776..d1e5f35cc7c53f 100644 --- a/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryMapping.java +++ b/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryMapping.java @@ -17,6 +17,8 @@ import com.google.auto.value.AutoValue; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Interner; +import com.google.devtools.build.lib.concurrent.BlazeInterners; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -34,6 +36,15 @@ @AutoValue public abstract class RepositoryMapping { + // All repositories generated by a module extension have the same repository mapping + // entries. Without interning, if a module extension generates N repositories, each such + // repository would have its own copy with (more than) N entries, resulting in memory usage that + // is quadratic in N. + // Note: We intern the entries, not the RepositoryMapping itself, because the latter also includes + // the owner repo, which differs between extension repos. + private static final Interner> ENTRIES_INTERNER = + BlazeInterners.newWeakInterner(); + // Always fallback to the requested name public static final RepositoryMapping ALWAYS_FALLBACK = createAllowingFallback(ImmutableMap.of()); @@ -60,7 +71,8 @@ public static RepositoryMapping createAllowingFallback(Map entries, RepositoryName ownerRepo) { - return new AutoValue_RepositoryMapping(ImmutableMap.copyOf(entries), ownerRepo); + return new AutoValue_RepositoryMapping( + ENTRIES_INTERNER.intern(ImmutableMap.copyOf(entries)), ownerRepo); } /**