commit f5bd73e84bdc68a6e85196e75c813d0686ecbe91
parent 54cfe2b0ceb73aede1442d2e01106f7fbd031de8
Author: serge-sans-paille <sguelton@mozilla.com>
Date: Wed, 17 Dec 2025 10:49:42 +0000
Bug 2003230 - optimize chunk_by_runtime.get_manifest for the Linux case r=jcristau
Optimizing get_manifest in the common case of os.sep == '/' yields a
nice 138ms gain on task graph rebuild.
% hyperfine -L branch experiment/try-validate^,experiment/try-validate -w1 -r5 -s 'git checkout {branch}' 'TASKGRAPH_SERIAL=1 ./mach taskgraph full -k mochitest'
Benchmark 1: TASKGRAPH_SERIAL=1 ./mach taskgraph full -k mochitest (branch = experiment/try-validate^)
Time (mean ± σ): 19.569 s ± 0.081 s [User: 19.841 s, System: 2.932 s]
Range (min … max): 19.440 s … 19.653 s 5 runs
Benchmark 2: TASKGRAPH_SERIAL=1 ./mach taskgraph full -k mochitest (branch = experiment/try-validate)
Time (mean ± σ): 19.431 s ± 0.077 s [User: 19.676 s, System: 3.008 s]
Range (min … max): 19.343 s … 19.511 s 5 runs
Summary
TASKGRAPH_SERIAL=1 ./mach taskgraph full -k mochitest (branch = experiment/try-validate) ran
1.01 ± 0.01 times faster than TASKGRAPH_SERIAL=1 ./mach taskgraph full -k mochitest (branch = experiment/try-validate^)
Differential Revision: https://phabricator.services.mozilla.com/D274553
Diffstat:
2 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/testing/mozbase/manifestparser/manifestparser/filters.py b/testing/mozbase/manifestparser/manifestparser/filters.py
@@ -16,7 +16,7 @@ from collections.abc import MutableSequence
from .expression import ParseError, parse
from .logger import Logger
-from .util import normsep
+from .util import norm_needed, normsep
# built-in filters
@@ -333,17 +333,30 @@ class chunk_by_runtime(InstanceFilter):
self.runtimes = {normsep(m): r for m, r in runtimes.items()}
self.logger = Logger()
- @classmethod
- def get_manifest(cls, test):
- manifest = normsep(test.get("ancestor_manifest", ""))
-
- # Ignore ancestor_manifests that live at the root (e.g, don't have a
- # path separator). The only time this should happen is when they are
- # generated by the build system and we shouldn't count generated
- # manifests for chunking purposes.
- if not manifest or "/" not in manifest:
- manifest = normsep(test["manifest_relpath"])
- return manifest
+ # NOTE: get_manifest is called a lot, so we 'inline' normsep when it's
+ # profitable.
+ if norm_needed:
+
+ @staticmethod
+ def get_manifest(test):
+ manifest = normsep(test.get("ancestor_manifest", ""))
+
+ # Ignore ancestor_manifests that live at the root (e.g, don't have a
+ # path separator). The only time this should happen is when they are
+ # generated by the build system and we shouldn't count generated
+ # manifests for chunking purposes.
+ if not manifest or "/" not in manifest:
+ manifest = normsep(test["manifest_relpath"])
+ return manifest
+
+ else:
+
+ @staticmethod
+ def get_manifest(test):
+ manifest = test.get("ancestor_manifest")
+ return (
+ manifest if manifest and "/" in manifest else test["manifest_relpath"]
+ )
def get_chunked_manifests(self, manifests):
# Find runtimes for all relevant manifests.
diff --git a/testing/mozbase/manifestparser/manifestparser/util.py b/testing/mozbase/manifestparser/manifestparser/util.py
@@ -14,6 +14,8 @@ if os.altsep and os.altsep != "/":
if os.sep != "/":
sep_b = os.sep.encode("ascii")
+norm_needed = True
+
if os.sep != "/":
if os.altsep and os.altsep != "/":
@@ -53,6 +55,8 @@ else:
def normsep(path):
return path
+ norm_needed = False # noqa: F841
+
def evaluate_list_from_string(list_string):
"""