Bug 1305877 - Add a directory hash chunker; r=jgraham
authorGregory Szorc <gps@mozilla.com>
Thu, 29 Sep 2016 14:42:50 -0700
changeset 316394 93d193ddedc921ba29e3acca55d14984ed86b642
parent 316393 83f4e83b4f1affa63eb0996c4b0569def827d389
child 316395 60ab329a382b54a553fc5fd72f892229aefed1a6
push id32811
push usergszorc@mozilla.com
push dateTue, 04 Oct 2016 14:46:40 +0000
treeherderautoland@604451ab5829 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgraham
bugs1305877
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1305877 - Add a directory hash chunker; r=jgraham Per discussion in the bug, we want automation to behave like local development mode with regards to running tests in a directory. That means we want all tests in a directory to be executed together. We introduce a directory hash chunker. It is like the HashChunker except it hashes the directory of the test (not the full path). This ensures that all tests in the same directory end up in the same chunk. Compared to HashChunker, this will likely make slow directories contribute to higher variance in chunk execution times. MozReview-Commit-ID: CeV0Gi6NRRp
testing/web-platform/harness/wptrunner/testloader.py
testing/web-platform/harness/wptrunner/wptcommandline.py
--- a/testing/web-platform/harness/wptrunner/testloader.py
+++ b/testing/web-platform/harness/wptrunner/testloader.py
@@ -46,16 +46,30 @@ class HashChunker(TestChunker):
     def __call__(self, manifest):
         chunk_index = self.chunk_number - 1
         for test_path, tests in manifest:
             h = int(hashlib.md5(test_path).hexdigest(), 16)
             if h % self.total_chunks == chunk_index:
                 yield test_path, tests
 
 
+class DirectoryHashChunker(TestChunker):
+    """Like HashChunker except the directory is hashed.
+
+    This ensures that all tests in the same directory end up in the same
+    chunk.
+    """
+    def __call__(self, manifest):
+        chunk_index = self.chunk_number - 1
+        for test_path, tests in manifest:
+            h = int(hashlib.md5(os.path.dirname(test_path)).hexdigest(), 16)
+            if h % self.total_chunks == chunk_index:
+                yield test_path, tests
+
+
 class EqualTimeChunker(TestChunker):
     def _group_by_directory(self, manifest_items):
         """Split the list of manifest items into a ordered dict that groups tests in
         so that anything in the same subdirectory beyond a depth of 3 is in the same
         group. So all tests in a/b/c, a/b/c/d and a/b/c/e will be grouped together
         and separate to tests in a/b/f
 
         Returns: tuple (ordered dict of {test_dir: PathData}, total estimated runtime)
@@ -446,16 +460,17 @@ class TestLoader(object):
         self.include_https = include_https
 
         self.chunk_type = chunk_type
         self.total_chunks = total_chunks
         self.chunk_number = chunk_number
 
         self.chunker = {"none": Unchunked,
                         "hash": HashChunker,
+                        "dir_hash": DirectoryHashChunker,
                         "equal_time": EqualTimeChunker}[chunk_type](total_chunks,
                                                                     chunk_number)
 
         self._test_ids = None
 
         self.directory_manifests = {}
 
         self._load_tests()
--- a/testing/web-platform/harness/wptrunner/wptcommandline.py
+++ b/testing/web-platform/harness/wptrunner/wptcommandline.py
@@ -140,17 +140,17 @@ scheme host and port.""")
                             help="Build is a release (overrides any mozinfo file)")
 
 
     chunking_group = parser.add_argument_group("Test Chunking")
     chunking_group.add_argument("--total-chunks", action="store", type=int, default=1,
                                 help="Total number of chunks to use")
     chunking_group.add_argument("--this-chunk", action="store", type=int, default=1,
                                 help="Chunk number to run")
-    chunking_group.add_argument("--chunk-type", action="store", choices=["none", "equal_time", "hash"],
+    chunking_group.add_argument("--chunk-type", action="store", choices=["none", "equal_time", "hash", "dir_hash"],
                                 default=None, help="Chunking type to use")
 
     ssl_group = parser.add_argument_group("SSL/TLS")
     ssl_group.add_argument("--ssl-type", action="store", default=None,
                         choices=["openssl", "pregenerated", "none"],
                         help="Type of ssl support to enable (running without ssl may lead to spurious errors)")
 
     ssl_group.add_argument("--openssl-binary", action="store",