summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Gross <grossag@vmware.com>2019-11-25 15:59:49 (GMT)
committerAdam Gross <grossag@vmware.com>2019-11-25 15:59:49 (GMT)
commit3b0b2b13b3b47886bd097685c863068a5ca8c5dd (patch)
treeeb2201f478ae5d7d5a3d29c6700239429bc6726b
parent49b5f9ec268d6f913088cae0b2942f5c7a139693 (diff)
downloadSCons-3b0b2b13b3b47886bd097685c863068a5ca8c5dd.zip
SCons-3b0b2b13b3b47886bd097685c863068a5ca8c5dd.tar.gz
SCons-3b0b2b13b3b47886bd097685c863068a5ca8c5dd.tar.bz2
Memoize environment.Value() to improve performance
The code I work on calls env.Value() often on the same values as part of consolidating outside dependencies. This change improves performance of that call by memoizing the results.
-rw-r--r--src/engine/SCons/Environment.py2
-rw-r--r--src/engine/SCons/Node/Python.py30
2 files changed, 25 insertions, 7 deletions
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index 1296f54..968cc9f 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -2220,7 +2220,7 @@ class Base(SubstitutionEnvironment):
def Value(self, value, built_value=None):
"""
"""
- return SCons.Node.Python.Value(value, built_value)
+ return SCons.Node.Python.ValueWithMemo(value, built_value)
def VariantDir(self, variant_dir, src_dir, duplicate=1):
variant_dir = self.arg2nodes(variant_dir, self.fs.Dir)[0]
diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py
index 4a62f04..f817402 100644
--- a/src/engine/SCons/Node/Python.py
+++ b/src/engine/SCons/Node/Python.py
@@ -31,6 +31,9 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.Node
+_memoLookupMap = {}
+
+
class ValueNodeInfo(SCons.Node.NodeInfoBase):
__slots__ = ('csig',)
current_version_id = 2
@@ -38,18 +41,18 @@ class ValueNodeInfo(SCons.Node.NodeInfoBase):
field_list = ['csig']
def str_to_node(self, s):
- return Value(s)
+ return ValueWithMemo(s)
def __getstate__(self):
"""
Return all fields that shall be pickled. Walk the slots in the class
- hierarchy and add those to the state dictionary. If a '__dict__' slot is
- available, copy all entries to the dictionary. Also include the version
- id, which is fixed for all instances of a class.
+ hierarchy and add those to the state dictionary. If a '__dict__' slot
+ is available, copy all entries to the dictionary. Also include the
+ version id, which is fixed for all instances of a class.
"""
state = getattr(self, '__dict__', {}).copy()
for obj in type(self).mro():
- for name in getattr(obj,'__slots__',()):
+ for name in getattr(obj, '__slots__', ()):
if hasattr(self, name):
state[name] = getattr(self, name)
@@ -76,6 +79,7 @@ class ValueBuildInfo(SCons.Node.BuildInfoBase):
__slots__ = ()
current_version_id = 2
+
class Value(SCons.Node.Node):
"""A class for Python variables, typically passed on the command line
or generated by a script, but not from a file or some other source.
@@ -148,7 +152,6 @@ class Value(SCons.Node.Node):
# Already encoded as python2 str are bytes
return text_contents
-
def changed_since_last_build(self, target, prev_ni):
cur_csig = self.get_csig()
try:
@@ -173,6 +176,21 @@ class Value(SCons.Node.Node):
self.get_ninfo().csig = contents
return contents
+
+def ValueWithMemo(value, built_value=None):
+ # No current support for memoizing a value that needs to be built.
+ if built_value:
+ return Value(value, built_value)
+
+ value_str = str(value)
+ if value_str in _memoLookupMap:
+ return _memoLookupMap[value_str]
+
+ v = Value(value)
+ _memoLookupMap[value_str] = v
+ return v
+
+
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil