Skip to content

Commit

Permalink
ninjabackend: avoid repeatedly building and analyzing rule commands
Browse files Browse the repository at this point in the history
Two expensive parts of length_estimate() are executed for each target, but they are really
always the same.  Cache them in __init__, there will always be more targets than rules in
cases where speed counts.

Signed-off-by: Paolo Bonzini <[email protected]>
  • Loading branch information
bonzini authored and eli-schwartz committed Jan 8, 2025
1 parent 4151d09 commit 5af3d3d
Showing 1 changed file with 14 additions and 13 deletions.
27 changes: 14 additions & 13 deletions mesonbuild/backend/ninjabackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ def strToCommandArg(c: T.Union[NinjaCommandArg, str]) -> NinjaCommandArg:
self.refcount = 0
self.rsprefcount = 0
self.rspfile_quote_style = rspfile_quote_style
self.command_str = ' '.join([self._quoter(x) for x in self.command + self.args])
self.var_refs = [m for m in re.finditer(r'(\${\w+}|\$\w+)?[^$]*', self.command_str)
if m.start(1) != -1]

if self.depfile == '$DEPFILE':
self.depfile += '_UNQUOTED'
Expand Down Expand Up @@ -262,7 +265,7 @@ def rule_iter() -> T.Iterable[str]:
outfile.write(' rspfile = $out.rsp\n')
outfile.write(' rspfile_content = {}\n'.format(' '.join([self._quoter(x, rspfile_quote_func) for x in rspfile_args])))
else:
outfile.write(' command = {}\n'.format(' '.join([self._quoter(x) for x in self.command + self.args])))
outfile.write(' command = {}\n'.format(self.command_str))
if self.deps:
outfile.write(f' deps = {self.deps}\n')
if self.depfile:
Expand All @@ -289,18 +292,16 @@ def length_estimate(self, infiles: str, outfiles: str,
ninja_vars['out'] = [outfiles]

# expand variables in command
command = ' '.join([self._quoter(x) for x in self.command + self.args])
estimate = len(command)
for m in re.finditer(r'(\${\w+}|\$\w+)?[^$]*', command):
if m.start(1) != -1:
estimate -= m.end(1) - m.start(1)
chunk = m.group(1)
if chunk[1] == '{':
chunk = chunk[2:-1]
else:
chunk = chunk[1:]
chunk = ninja_vars.get(chunk, []) # undefined ninja variables are empty
estimate += len(' '.join(chunk))
estimate = len(self.command_str)
for m in self.var_refs:
estimate -= m.end(1) - m.start(1)
chunk = m.group(1)
if chunk[1] == '{':
chunk = chunk[2:-1]
else:
chunk = chunk[1:]
chunk = ninja_vars.get(chunk, []) # undefined ninja variables are empty
estimate += len(' '.join(chunk))

# determine command length
return estimate
Expand Down

0 comments on commit 5af3d3d

Please sign in to comment.