From e22d3250dd78eac769906620da55594690fbbca7 Mon Sep 17 00:00:00 2001
From: Todd Gamblin <tgamblin@llnl.gov>
Date: Sat, 21 Dec 2019 23:45:47 -0800
Subject: [PATCH] performance: dont' read `spec.yaml` files twice in view
 regeneration

`ViewDescriptor.regenerate()` calls `get_all_specs()`, which reads
`spec.yaml` files, which is slow.  It's fine to do this once, but
`view.remove_specs()` *also* calls it immediately afterwards.

- [x] Pass the result of `get_all_specs()` as an optional parameter to
  `view.remove_specs()` to avoid reading `spec.yaml` files twice.
---
 lib/spack/spack/environment.py     | 7 +++++--
 lib/spack/spack/filesystem_view.py | 5 +++--
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/lib/spack/spack/environment.py b/lib/spack/spack/environment.py
index 56440fbe92..bf9af075ce 100644
--- a/lib/spack/spack/environment.py
+++ b/lib/spack/spack/environment.py
@@ -534,9 +534,12 @@ def regenerate(self, all_specs, roots):
             tty.msg("Updating view at {0}".format(self.root))
 
             rm_specs = specs_in_view - installed_specs_for_view
-            view.remove_specs(*rm_specs, with_dependents=False)
-
             add_specs = installed_specs_for_view - specs_in_view
+
+            # pass all_specs in, as it's expensive to read all the
+            # spec.yaml files twice.
+            view.remove_specs(*rm_specs, with_dependents=False,
+                              all_specs=specs_in_view)
             view.add_specs(*add_specs, with_dependencies=False)
 
 
diff --git a/lib/spack/spack/filesystem_view.py b/lib/spack/spack/filesystem_view.py
index 448254f26b..5455ccb107 100644
--- a/lib/spack/spack/filesystem_view.py
+++ b/lib/spack/spack/filesystem_view.py
@@ -371,6 +371,9 @@ def remove_specs(self, *specs, **kwargs):
         with_dependents = kwargs.get("with_dependents", True)
         with_dependencies = kwargs.get("with_dependencies", False)
 
+        # caller can pass this in, as get_all_specs() is expensive
+        all_specs = kwargs.get("all_specs", None) or set(self.get_all_specs())
+
         specs = set(specs)
 
         if with_dependencies:
@@ -379,8 +382,6 @@ def remove_specs(self, *specs, **kwargs):
         if kwargs.get("exclude", None):
             specs = set(filter_exclude(specs, kwargs["exclude"]))
 
-        all_specs = set(self.get_all_specs())
-
         to_deactivate = specs
         to_keep = all_specs - to_deactivate
 
-- 
GitLab