From b14601da7b42f2b68bb098fc04e267a390f201c2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Aug 2020 15:33:12 +0200 Subject: [PATCH] ninjabackend: optimize length_estimate Optimize the regular expression so that the variable expansion part always ends up in group 1, and the trailer after the variable is discarded in the same match. Do not use re.sub to remove braces, and do not bother building the expanded command, just adjust the estimated length on the fly. functools.reduce is extremely slow, so I am keeping ' '.join(chunk). On a QEMU build the time spend in the function goes from 1.072s to 0.757s. --- mesonbuild/backend/ninjabackend.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 5f7f03a67..fd8be0098 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -265,18 +265,20 @@ class NinjaRule: # expand variables in command command = ' '.join([self._quoter(x) for x in self.command + self.args]) - expanded_command = '' - for m in re.finditer(r'(\${\w*})|(\$\w*)|([^$]*)', command): - chunk = m.group() - if chunk.startswith('$'): - chunk = chunk[1:] - chunk = re.sub(r'{(.*)}', r'\1', chunk) - chunk = ninja_vars.get(chunk, []) # undefined ninja variables are empty - chunk = ' '.join(chunk) - expanded_command += chunk + estimate = len(command) + for m in re.finditer(r'(\${\w*}|\$\w*)?[^$]*', command): + if m.start(1) != -1: + estimate -= m.end(1) - m.start(1) + 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 len(expanded_command) + return estimate class NinjaBuildElement: def __init__(self, all_outputs, outfilenames, rulename, infilenames, implicit_outs=None):