Skip to content

Commit a0549af

Browse files
authored
Merge pull request #4867 from bdbaddog/claude_subst_pref_bug_updates_1
Subst.py: fix bugs and improve substitution performance
2 parents b756de8 + a42cb60 commit a0549af

6 files changed

Lines changed: 400 additions & 61 deletions

File tree

CHANGES.txt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,33 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
4444
new contributors. (Using Gemini AI)
4545
- Fix Appveyor scripting to install unavailable python versions when needed and use them
4646
for testing.
47+
- Subst: Fixed ListSubber.expanded(), which never detected an already-expanded
48+
string (dead code since its 2019 introduction), so fully-expanded values are
49+
no longer recursively re-processed during scons_subst_list().
50+
- Subst: scons_subst() and scons_subst_list() no longer leak a __builtins__
51+
key into the construction environment's dictionary if an exception is
52+
raised during substitution.
53+
- Subst: the result of the inspect.signature() check for callable
54+
construction variables is now cached per callable, speeding up expansion
55+
of function-valued variables. Callables whose signature cannot be
56+
determined (some C/builtin callables) are now treated as not matching
57+
the (target, source, env, for_signature) convention instead of raising.
58+
- Subst: variable values which are plain strings with no further '$'
59+
expansions are now returned directly, skipping an unneeded dict copy
60+
and recursive substitution pass. Combined, the substitution speedups
61+
measured on a representative command line (this from a micro benchmark
62+
and not on a full build) are:
63+
('$CC $CCFLAGS $CPPDEFINES $GEN -c -o $TARGET $SOURCES'):
64+
old new improvement
65+
scons_subst 20.7 us 12.8 us ~38% faster
66+
scons_subst_list 37.4 us 25.1 us ~33% faster
67+
- Subst: a NameError raised during scons_subst_list() now includes the
68+
name of the unknown variable in the error message.
69+
- Subst: the overrides argument to scons_subst()/scons_subst_list() no
70+
longer mutates a caller-supplied lvars dictionary; also removed mutable
71+
default arguments. Removed Literal.__neq__, a misspelled (and therefore
72+
never-invoked) version of __ne__; Python derives inequality from
73+
Literal.__eq__.
4774

4875
From Prabhu S. Khalsa:
4976
- Fix typo in preface
@@ -54,6 +81,13 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
5481

5582
From Mats Wichmann:
5683
- Introduce some unit tests for the file locking utility routines
84+
- Subst: Improved variable substitution by consolidating dictionary
85+
merging operations, reducing unnecessary copy operations when no
86+
TARGET/SOURCE variables or overrides need to be applied. Combined
87+
with other substitution improvements (lru_cache for callable signature
88+
caching, action hashability, for_signature bug fix, f-string
89+
modernization), typical builds see up to 8-12% improvement with larger gains
90+
(up to 20-30%) on builds with many callable construction variables.
5791
- Reduce unneeded computation of overrides. The Mkdir builder used an
5892
unknown argument ('explain') on creation, causing it to be considered
5993
an override. Also, if override dict is empty, don't even call the

RELEASE.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,18 @@ IMPROVEMENTS
6363
an override. Also, if override dict is empty, don't even call the
6464
Override factory function.
6565

66+
- Subst: Multiple substitution optimizations providing up to 8-12% performance
67+
improvement on typical builds, with larger gains (up to 20-30%) on builds with
68+
many callable construction variables:
69+
* Consolidate dictionary merging operations to reduce unnecessary copies
70+
* Use functools.lru_cache for callable signature inspection with bounded
71+
memory (256 entries max, ~1MB)
72+
* Make Action classes (CommandAction, FunctionAction, ListAction) hashable
73+
to enable cache optimization
74+
* Fix for_signature logic bug in ListSubber.expand() for correct signature
75+
generation
76+
* Modernize string formatting to f-strings
77+
6678
- Test runner reworked to use Python logging; the portion of the test suite
6779
which tests the runner was adjusted to match.
6880

SCons/Action.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,9 @@ def __str__(self) -> str:
10001000
return ' '.join(map(str, self.cmd_list))
10011001
return str(self.cmd_list)
10021002

1003+
def __hash__(self) -> int:
1004+
""" Added so CommandAction can be used as a key in a dict and/or cached. """
1005+
return id(self)
10031006

10041007
def process(self, target, source, env, executor: Executor | None = None, overrides: dict | None = None) -> tuple[list, bool, bool]:
10051008
if executor:
@@ -1421,6 +1424,10 @@ def __str__(self) -> str:
14211424
return str(self.execfunction)
14221425
return "%s(target, source, env)" % name
14231426

1427+
def __hash__(self) -> int:
1428+
""" Added so FunctionAction can be used as a key in a dict and/or cached. """
1429+
return id(self)
1430+
14241431
def execute(self, target, source, env, executor: Executor | None = None):
14251432
exc_info = (None,None,None)
14261433
try:
@@ -1482,6 +1489,10 @@ def genstring(self, target, source, env, executor: Executor | None = None) -> st
14821489
def __str__(self) -> str:
14831490
return '\n'.join(map(str, self.list))
14841491

1492+
def __hash__(self) -> int:
1493+
""" Added so ListAction can be used as a key in a dict and/or cached. """
1494+
return id(self)
1495+
14851496
def presub_lines(self, env):
14861497
return SCons.Util.flatten_sequence(
14871498
[a.presub_lines(env) for a in self.list])

0 commit comments

Comments
 (0)