summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMassimiliano Culpo <massimiliano.culpo@gmail.com>2023-06-01 22:36:42 +0200
committerGitHub <noreply@github.com>2023-06-01 13:36:42 -0700
commit42667fe7fa1182759f0d2bf3b9637038d345dc78 (patch)
treeb60d3869ec56d195f838fc86e5bf489d3181249c
parentcd27611d2f601a04aab1bed10fd2d728ef20c24e (diff)
downloadspack-42667fe7fa1182759f0d2bf3b9637038d345dc78.tar.gz
spack-42667fe7fa1182759f0d2bf3b9637038d345dc78.tar.bz2
spack-42667fe7fa1182759f0d2bf3b9637038d345dc78.tar.xz
spack-42667fe7fa1182759f0d2bf3b9637038d345dc78.zip
Memoize a few hot functions during module file generation (#37739)
-rw-r--r--lib/spack/spack/modules/common.py4
-rw-r--r--lib/spack/spack/modules/lmod.py5
-rw-r--r--lib/spack/spack/tengine.py16
-rw-r--r--lib/spack/spack/test/relocate.py2
-rw-r--r--lib/spack/spack/test/tengine.py2
5 files changed, 16 insertions, 13 deletions
diff --git a/lib/spack/spack/modules/common.py b/lib/spack/spack/modules/common.py
index 278038510a..ef3f751471 100644
--- a/lib/spack/spack/modules/common.py
+++ b/lib/spack/spack/modules/common.py
@@ -170,11 +170,9 @@ def merge_config_rules(configuration, spec):
Returns:
dict: actions to be taken on the spec passed as an argument
"""
- # Construct a dictionary with the actions we need to perform on the spec passed as a parameter
- spec_configuration = {}
# The keyword 'all' is always evaluated first, all the others are
# evaluated in order of appearance in the module file
- spec_configuration.update(copy.deepcopy(configuration.get("all", {})))
+ spec_configuration = copy.deepcopy(configuration.get("all", {}))
for constraint, action in configuration.items():
if spec.satisfies(constraint):
if hasattr(constraint, "override") and constraint.override:
diff --git a/lib/spack/spack/modules/lmod.py b/lib/spack/spack/modules/lmod.py
index 64c8c49b7e..0abead05b6 100644
--- a/lib/spack/spack/modules/lmod.py
+++ b/lib/spack/spack/modules/lmod.py
@@ -134,6 +134,7 @@ class LmodConfiguration(BaseConfiguration):
return configuration(self.name).get("filter_hierarchy_specs", {})
@property
+ @lang.memoized
def hierarchy_tokens(self):
"""Returns the list of tokens that are part of the modulefile
hierarchy. 'compiler' is always present.
@@ -158,6 +159,7 @@ class LmodConfiguration(BaseConfiguration):
return tokens
@property
+ @lang.memoized
def requires(self):
"""Returns a dictionary mapping all the requirements of this spec
to the actual provider. 'compiler' is always present among the
@@ -224,6 +226,7 @@ class LmodConfiguration(BaseConfiguration):
return available
@property
+ @lang.memoized
def missing(self):
"""Returns the list of tokens that are not available."""
return [x for x in self.hierarchy_tokens if x not in self.available]
@@ -317,6 +320,7 @@ class LmodFileLayout(BaseFileLayout):
return parts
@property
+ @lang.memoized
def unlocked_paths(self):
"""Returns a dictionary mapping conditions to a list of unlocked
paths.
@@ -428,6 +432,7 @@ class LmodContext(BaseContext):
return self.conf.missing
@tengine.context_property
+ @lang.memoized
def unlocked_paths(self):
"""Returns the list of paths that are unlocked unconditionally."""
layout = make_layout(self.spec, self.conf.name, self.conf.explicit)
diff --git a/lib/spack/spack/tengine.py b/lib/spack/spack/tengine.py
index 86c5235a57..6a77e6becf 100644
--- a/lib/spack/spack/tengine.py
+++ b/lib/spack/spack/tengine.py
@@ -4,7 +4,7 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import itertools
import textwrap
-from typing import List
+from typing import List, Optional, Tuple
import llnl.util.lang
@@ -66,17 +66,17 @@ class Context(metaclass=ContextMeta):
return dict(d)
-def make_environment(dirs=None):
- """Returns an configured environment for template rendering."""
+@llnl.util.lang.memoized
+def make_environment(dirs: Optional[Tuple[str, ...]] = None):
+ """Returns a configured environment for template rendering."""
+ # Import at this scope to avoid slowing Spack startup down
+ import jinja2
+
if dirs is None:
# Default directories where to search for templates
builtins = spack.config.get("config:template_dirs", ["$spack/share/spack/templates"])
extensions = spack.extensions.get_template_dirs()
- dirs = [canonicalize_path(d) for d in itertools.chain(builtins, extensions)]
-
- # avoid importing this at the top level as it's used infrequently and
- # slows down startup a bit.
- import jinja2
+ dirs = tuple(canonicalize_path(d) for d in itertools.chain(builtins, extensions))
# Loader for the templates
loader = jinja2.FileSystemLoader(dirs)
diff --git a/lib/spack/spack/test/relocate.py b/lib/spack/spack/test/relocate.py
index 1b14ad9fbb..a0553d4422 100644
--- a/lib/spack/spack/test/relocate.py
+++ b/lib/spack/spack/test/relocate.py
@@ -62,7 +62,7 @@ def source_file(tmpdir, is_relocatable):
src = tmpdir.join("relocatable.c")
shutil.copy(template_src, str(src))
else:
- template_dirs = [os.path.join(spack.paths.test_path, "data", "templates")]
+ template_dirs = (os.path.join(spack.paths.test_path, "data", "templates"),)
env = spack.tengine.make_environment(template_dirs)
template = env.get_template("non_relocatable.c")
text = template.render({"prefix": spack.store.layout.root})
diff --git a/lib/spack/spack/test/tengine.py b/lib/spack/spack/test/tengine.py
index 3ade233160..95362c33fa 100644
--- a/lib/spack/spack/test/tengine.py
+++ b/lib/spack/spack/test/tengine.py
@@ -71,7 +71,7 @@ class TestTengineEnvironment(object):
"""Tests the template retrieval mechanism hooked into config files"""
# Check the directories are correct
template_dirs = spack.config.get("config:template_dirs")
- template_dirs = [canonicalize_path(x) for x in template_dirs]
+ template_dirs = tuple([canonicalize_path(x) for x in template_dirs])
assert len(template_dirs) == 3
env = tengine.make_environment(template_dirs)