Memoize a few hot functions during module file generation (#37739)
This commit is contained in:
		 Massimiliano Culpo
					Massimiliano Culpo
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							cd27611d2f
						
					
				
				
					commit
					42667fe7fa
				
			| @@ -170,11 +170,9 @@ def merge_config_rules(configuration, spec): | |||||||
|     Returns: |     Returns: | ||||||
|         dict: actions to be taken on the spec passed as an argument |         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 |     # The keyword 'all' is always evaluated first, all the others are | ||||||
|     # evaluated in order of appearance in the module file |     # 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(): |     for constraint, action in configuration.items(): | ||||||
|         if spec.satisfies(constraint): |         if spec.satisfies(constraint): | ||||||
|             if hasattr(constraint, "override") and constraint.override: |             if hasattr(constraint, "override") and constraint.override: | ||||||
|   | |||||||
| @@ -134,6 +134,7 @@ def filter_hierarchy_specs(self): | |||||||
|         return configuration(self.name).get("filter_hierarchy_specs", {}) |         return configuration(self.name).get("filter_hierarchy_specs", {}) | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|  |     @lang.memoized | ||||||
|     def hierarchy_tokens(self): |     def hierarchy_tokens(self): | ||||||
|         """Returns the list of tokens that are part of the modulefile |         """Returns the list of tokens that are part of the modulefile | ||||||
|         hierarchy. 'compiler' is always present. |         hierarchy. 'compiler' is always present. | ||||||
| @@ -158,6 +159,7 @@ def hierarchy_tokens(self): | |||||||
|         return tokens |         return tokens | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|  |     @lang.memoized | ||||||
|     def requires(self): |     def requires(self): | ||||||
|         """Returns a dictionary mapping all the requirements of this spec |         """Returns a dictionary mapping all the requirements of this spec | ||||||
|         to the actual provider. 'compiler' is always present among the |         to the actual provider. 'compiler' is always present among the | ||||||
| @@ -224,6 +226,7 @@ def available(self): | |||||||
|         return available |         return available | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|  |     @lang.memoized | ||||||
|     def missing(self): |     def missing(self): | ||||||
|         """Returns the list of tokens that are not available.""" |         """Returns the list of tokens that are not available.""" | ||||||
|         return [x for x in self.hierarchy_tokens if x not in self.available] |         return [x for x in self.hierarchy_tokens if x not in self.available] | ||||||
| @@ -317,6 +320,7 @@ def available_path_parts(self): | |||||||
|         return parts |         return parts | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|  |     @lang.memoized | ||||||
|     def unlocked_paths(self): |     def unlocked_paths(self): | ||||||
|         """Returns a dictionary mapping conditions to a list of unlocked |         """Returns a dictionary mapping conditions to a list of unlocked | ||||||
|         paths. |         paths. | ||||||
| @@ -428,6 +432,7 @@ def missing(self): | |||||||
|         return self.conf.missing |         return self.conf.missing | ||||||
| 
 | 
 | ||||||
|     @tengine.context_property |     @tengine.context_property | ||||||
|  |     @lang.memoized | ||||||
|     def unlocked_paths(self): |     def unlocked_paths(self): | ||||||
|         """Returns the list of paths that are unlocked unconditionally.""" |         """Returns the list of paths that are unlocked unconditionally.""" | ||||||
|         layout = make_layout(self.spec, self.conf.name, self.conf.explicit) |         layout = make_layout(self.spec, self.conf.name, self.conf.explicit) | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
| # SPDX-License-Identifier: (Apache-2.0 OR MIT) | # SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||||||
| import itertools | import itertools | ||||||
| import textwrap | import textwrap | ||||||
| from typing import List | from typing import List, Optional, Tuple | ||||||
| 
 | 
 | ||||||
| import llnl.util.lang | import llnl.util.lang | ||||||
| 
 | 
 | ||||||
| @@ -66,17 +66,17 @@ def to_dict(self): | |||||||
|         return dict(d) |         return dict(d) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def make_environment(dirs=None): | @llnl.util.lang.memoized | ||||||
|     """Returns an configured environment for template rendering.""" | 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: |     if dirs is None: | ||||||
|         # Default directories where to search for templates |         # Default directories where to search for templates | ||||||
|         builtins = spack.config.get("config:template_dirs", ["$spack/share/spack/templates"]) |         builtins = spack.config.get("config:template_dirs", ["$spack/share/spack/templates"]) | ||||||
|         extensions = spack.extensions.get_template_dirs() |         extensions = spack.extensions.get_template_dirs() | ||||||
|         dirs = [canonicalize_path(d) for d in itertools.chain(builtins, extensions)] |         dirs = tuple(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 |  | ||||||
| 
 | 
 | ||||||
|     # Loader for the templates |     # Loader for the templates | ||||||
|     loader = jinja2.FileSystemLoader(dirs) |     loader = jinja2.FileSystemLoader(dirs) | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ def source_file(tmpdir, is_relocatable): | |||||||
|         src = tmpdir.join("relocatable.c") |         src = tmpdir.join("relocatable.c") | ||||||
|         shutil.copy(template_src, str(src)) |         shutil.copy(template_src, str(src)) | ||||||
|     else: |     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) |         env = spack.tengine.make_environment(template_dirs) | ||||||
|         template = env.get_template("non_relocatable.c") |         template = env.get_template("non_relocatable.c") | ||||||
|         text = template.render({"prefix": spack.store.layout.root}) |         text = template.render({"prefix": spack.store.layout.root}) | ||||||
|   | |||||||
| @@ -71,7 +71,7 @@ def test_template_retrieval(self): | |||||||
|         """Tests the template retrieval mechanism hooked into config files""" |         """Tests the template retrieval mechanism hooked into config files""" | ||||||
|         # Check the directories are correct |         # Check the directories are correct | ||||||
|         template_dirs = spack.config.get("config:template_dirs") |         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 |         assert len(template_dirs) == 3 | ||||||
| 
 | 
 | ||||||
|         env = tengine.make_environment(template_dirs) |         env = tengine.make_environment(template_dirs) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user