Only create the host configuration once per BuildConfiguration instance.

We seem to be calling this function many times creating a lot of garbage
(when creating the FragmentClassSet to be used as a cache key). However,
in regular builds we are currently only calling this with a few different
instances of BuildConfiguration ever.

RELNOTES: None.
PiperOrigin-RevId: 241897160
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
index 6ff9493..a090655 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
@@ -134,7 +134,7 @@
   private BuildConfiguration topLevelHostConfiguration;
   // Fragment-limited versions of the host configuration. It's faster to create/cache these here
   // than to store them in Skyframe.
-  private Map<FragmentClassSet, BuildConfiguration> hostConfigurationCache =
+  private Map<BuildConfiguration, BuildConfiguration> hostConfigurationCache =
       Maps.newConcurrentMap();
 
   private BuildConfigurationCollection configurations;
@@ -787,6 +787,16 @@
     if (config == null) {
       return topLevelHostConfiguration;
     }
+    // Currently, a single build doesn't use many different BuildConfiguration instances. Thus,
+    // having a cache per BuildConfiguration is efficient. It might lead to instances of otherwise
+    // identical configurations if multiple of these configs use the same fragment classes. However,
+    // these are cheap especially if there is only a small number of configs. Revisit and turn into
+    // a cache per FragmentClassSet if configuration trimming results in a much higher number of
+    // configuration instances.
+    BuildConfiguration hostConfig = hostConfigurationCache.get(config);
+    if (hostConfig != null) {
+      return hostConfig;
+    }
     // TODO(bazel-team): have the fragment classes be those required by the consuming target's
     // transitive closure. This isn't the same as the input configuration's fragment classes -
     // the latter may be a proper subset of the former.
@@ -805,10 +815,6 @@
         config.trimConfigurations()
             ? config.fragmentClasses()
             : FragmentClassSet.of(ruleClassProvider.getAllFragments());
-    BuildConfiguration hostConfig = hostConfigurationCache.get(fragmentClasses);
-    if (hostConfig != null) {
-      return hostConfig;
-    }
     // TODO(bazel-team): investigate getting the trimmed config from Skyframe instead of cloning.
     // This is the only place we instantiate BuildConfigurations outside of Skyframe, This can
     // produce surprising effects, such as requesting a configuration that's in the Skyframe cache
@@ -822,7 +828,7 @@
     BuildConfiguration trimmedConfig =
         topLevelHostConfiguration.clone(
             fragmentClasses, ruleClassProvider, skyframeExecutor.getDefaultBuildOptions());
-    hostConfigurationCache.put(fragmentClasses, trimmedConfig);
+    hostConfigurationCache.put(config, trimmedConfig);
     return trimmedConfig;
   }