Bug 1397438 - Add subtests support for talos base vs ref pageloader tests; r=jmaher
authorRob Wood <rwood@mozilla.com>
Thu, 21 Sep 2017 08:47:56 -0400
changeset 435467 87ffa54a5436b83fb090616af2849966c64144f3
parent 435466 d095506bd1d678c5a004ce12510707186f86963b
child 435468 2b87ee06ac0478e58c7a20be52b413f73ee630dc
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmaher
bugs1397438
milestone58.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 1397438 - Add subtests support for talos base vs ref pageloader tests; r=jmaher MozReview-Commit-ID: Gc4nBionzqw
testing/talos/talos.json
testing/talos/talos/output.py
testing/talos/talos/pageloader/chrome/pageloader.js
testing/talos/talos/pageloader/install.rdf
testing/talos/talos/pageloader/pageloader-signed.xpi
testing/talos/talos/results.py
testing/talos/talos/run_tests.py
testing/talos/talos/test.py
testing/talos/talos/tests/perf-reftest/.eslintrc.json
testing/talos/talos/tests/perf-reftest/bloom-basic-2.html
testing/talos/talos/tests/perf-reftest/bloom-basic-ref.html
testing/talos/talos/tests/perf-reftest/bloom-basic.html
testing/talos/talos/tests/perf-reftest/bloom_basic.manifest
testing/talos/talos/tests/perf-reftest/bloom_basic_ref.manifest
testing/talos/talos/tests/perf-reftest/coalesce-1.html
testing/talos/talos/tests/perf-reftest/coalesce-ref.html
testing/talos/talos/tests/perf-reftest/perf_reftest.manifest
testing/talos/talos/tests/perf-reftest/util.js
--- a/testing/talos/talos.json
+++ b/testing/talos/talos.json
@@ -65,20 +65,20 @@
         "svgr-e10s": {
             "tests": ["tsvgx", "tsvgr_opacity", "tart", "tscrollx", "tsvg_static"]
         },
         "svgr-stylo-disabled-e10s": {
             "tests": ["tsvgx", "tsvgr_opacity", "tart", "tscrollx", "tsvg_static"],
             "talos_options": ["--disable-stylo"]
         },
         "perf-reftest-e10s": {
-            "tests": ["bloom_basic"]
+            "tests": ["perf_reftest"]
         },
         "perf-reftest-stylo-disabled-e10s": {
-            "tests": ["bloom_basic"],
+            "tests": ["perf_reftest"],
             "talos_options": ["--disable-stylo"]
         },
         "perf-reftest-singletons-e10s": {
             "tests": ["perf_reftest_singletons"]
         },
         "perf-reftest-singletons-stylo-disabled-e10s": {
             "tests": ["perf_reftest_singletons"],
             "talos_options": ["--disable-stylo"]
--- a/testing/talos/talos/output.py
+++ b/testing/talos/talos/output.py
@@ -87,34 +87,38 @@ class Output(object):
                     # override the list of page results for each run
                     result.results = results
 
                 for result in tresults:
                     filtered_results = \
                         result.values(suite['name'],
                                       test.test_config['filters'])
                     vals.extend([[i['value'], j] for i, j in filtered_results])
+                    subtest_index = 0
                     for val, page in filtered_results:
                         if page == 'NULL':
                             # no real subtests
                             page = test.name()
                         subtest = {
                             'name': page,
                             'value': val['filtered'],
                             'replicates': replicates[page],
                         }
                         # if results are from a comparison test i.e. perf-reftest, it will also
                         # contain replicates for 'base' and 'reference'; we wish to keep those
                         # to reference; actual results were calculated as the difference of those
-                        base_runs = result.results[0].get('base_runs', None)
-                        ref_runs = result.results[0].get('ref_runs', None)
+                        base_runs = result.results[subtest_index].get('base_runs', None)
+                        ref_runs = result.results[subtest_index].get('ref_runs', None)
                         if base_runs and ref_runs:
                             subtest['base_replicates'] = base_runs
                             subtest['ref_replicates'] = ref_runs
+
                         subtests.append(subtest)
+                        subtest_index += 1
+
                         if test.test_config.get('lower_is_better') is not None:
                             subtest['lowerIsBetter'] = \
                                 test.test_config['lower_is_better']
                         if test.test_config.get('alert_threshold') is not None:
                             subtest['alertThreshold'] = \
                                 test.test_config['alert_threshold']
                         if test.test_config.get('unit'):
                             subtest['unit'] = test.test_config['unit']
--- a/testing/talos/talos/pageloader/chrome/pageloader.js
+++ b/testing/talos/talos/pageloader/chrome/pageloader.js
@@ -46,16 +46,17 @@ var useMozAfterPaint = false;
 var useFNBPaint = false;
 var gPaintWindow = window;
 var gPaintListener = false;
 var loadNoCache = false;
 var scrollTest = false;
 var gDisableE10S = false;
 var gUseE10S = false;
 var profilingInfo = false;
+var baseVsRef = false;
 
 var isIdleCallbackPending = false;
 
 // when TEST_DOES_OWN_TIMING, we need to store the time from the page as MozAfterPaint can be slower than pageload
 var gTime = -1;
 var gStartTime = -1;
 var gReference = -1;
 
@@ -197,17 +198,16 @@ function plInit() {
     if (startIndex > endIndex) {
       dumpLine("tp: error: startIndex >= endIndex");
       plStop(true);
     }
 
     pages = pages.slice(startIndex, endIndex + 1);
     pageUrls = pages.map(function(p) { return p.url.spec.toString(); });
     report = new Report();
-
     if (doRenderTest)
       renderReport = new Report();
 
     pageIndex = 0;
     if (profilingInfo) {
       TalosParentProfiler.beginTest(getCurrentPageShortName());
     }
 
@@ -395,19 +395,17 @@ function plLoadPage() {
     mm.removeMessageListener("PageLoader:LoadEvent", ContentListener);
     mm.removeMessageListener("PageLoader:RecordTime", ContentListener);
     mm.removeMessageListener("PageLoader:IdleCallbackSet", ContentListener);
     mm.removeMessageListener("PageLoader:IdleCallbackReceived", ContentListener);
     if (useFNBPaint) {
       mm.removeMessageListener("PageLoader:FNBPaintError", ContentListener);
     }
   };
-
   failTimeout.register(loadFail, timeout);
-
   // record which page we are about to open
   TalosParentProfiler.mark("Opening " + pages[pageIndex].url.pathQueryRef);
 
   if (reportRSS) {
     collectMemory(startAndLoadURI, pageName);
   } else {
     startAndLoadURI(pageName);
   }
@@ -560,17 +558,25 @@ function plRecordTime(time) {
   var i = pageIndex
   if (i < pages.length - 1) {
     i++;
   } else {
     i = 0;
   }
   var nextName = pages[i].url.spec;
   if (!recordedName) {
-    recordedName = pageUrls[pageIndex];
+    // when doing base vs ref type of test, add pre 'base' or 'ref' to reported page name;
+    // this is necessary so that if multiple subtests use same reference page, results for
+    // each ref page run will be kept separate for each base vs ref run, and not grouped
+    // into just one set of results values for everytime that reference page was loaded
+    if (baseVsRef) {
+      recordedName = pages[pageIndex].pre + pageUrls[pageIndex];
+    } else {
+      recordedName = pageUrls[pageIndex];
+    }
   }
   if (typeof(time) == "string") {
     var times = time.split(",");
     var names = recordedName.split(",");
     for (var t = 0; t < times.length; t++) {
       if (names.length == 1) {
         report.recordTime(names, times[t]);
       } else {
@@ -888,20 +894,21 @@ function plLoadURLsFromURI(manifestUri) 
     fstream.init(uriFile.file, -1, 0, 0);
   } catch (ex) {
       dumpLine("tp: the file %s doesn't exist" % uriFile.file);
       return null;
   }
 
   var lstream = fstream.QueryInterface(Ci.nsILineInputStream);
 
-  var d = [];
+  var url_array = [];
 
   var lineNo = 0;
   var line = {value: null};
+  var baseVsRefIndex = 0;
   var more;
   do {
     lineNo++;
     more = lstream.readLine(line);
     var s = line.value;
 
     // strip comments (only leading ones)
     s = s.replace(/^#.*/, "");
@@ -909,16 +916,17 @@ function plLoadURLsFromURI(manifestUri) 
     // strip leading and trailing whitespace
     s = s.replace(/^\s*/, "").replace(/\s*$/, "");
 
     if (!s)
       continue;
 
     var flags = 0;
     var urlspec = s;
+    baseVsRefIndex += 1;
 
     // split on whitespace, and figure out if we have any flags
     var items = s.split(/\s+/);
     if (items[0] == "include") {
       if (items.length != 2) {
         dumpLine("tp: Error on line " + lineNo + " in " + manifestUri.spec + ": include must be followed by the manifest to include!");
         return null;
       }
@@ -927,17 +935,17 @@ function plLoadURLsFromURI(manifestUri) 
       if (subManifest == null) {
         dumpLine("tp: invalid URI on line " + manifestUri.spec + ":" + lineNo + " : '" + line.value + "'");
         return null;
       }
 
       var subItems = plLoadURLsFromURI(subManifest);
       if (subItems == null)
         return null;
-      d = d.concat(subItems);
+      url_array = url_array.concat(subItems);
     } else {
       // For scrollTest flag, we accept "normal" pages but treat them as TEST_DOES_OWN_TIMING
       // together with EXECUTE_SCROLL_TEST which makes us run the scroll test on load.
       // We do this by artificially "injecting" the TEST_DOES_OWN_TIMING flag ("%") to the item
       // and then let the default flow for this flag run without further modifications
       // (other than calling the scroll test once the page is loaded).
       // Note that if we have the scrollTest flag but the item already has "%", then we do
       // nothing (the scroll test will not execute, and the page will report with its
@@ -947,32 +955,68 @@ function plLoadURLsFromURI(manifestUri) 
         flags |= EXECUTE_SCROLL_TEST;
       }
 
       if (items.length == 2) {
         if (items[0].indexOf("%") != -1)
           flags |= TEST_DOES_OWN_TIMING;
 
         urlspec = items[1];
+      } else if (items.length == 3) {
+        // base vs ref type of talos test
+        // expect each manifest line to be in the format of:
+        // & http://localhost/tests/perf-reftest/base-page.html, http://localhost/tests/perf-reftest/reference-page.html
+        // test will run with the base page, then with the reference page; and ultimately the actual test results will
+        // be the comparison values of those two pages; more than one line will result in base vs ref subtests
+        if (items[0].indexOf("&") != -1) {
+          baseVsRef = true;
+          flags |= TEST_DOES_OWN_TIMING;
+          // for the base, must remove the comma on the end of the actual url
+          var urlspecBase = items[1].slice(0, -1);
+          var urlspecRef = items[2];
+        } else {
+          dumpLine("tp: Error on line " + lineNo + " in " + manifestUri.spec + ": unknown manifest format!");
+          return null;
+        }
       } else if (items.length != 1) {
         dumpLine("tp: Error on line " + lineNo + " in " + manifestUri.spec + ": whitespace must be %-escaped!");
         return null;
       }
 
-      var url = gIOS.newURI(urlspec, null, manifestUri);
+      var url;
+
+      if (!baseVsRef) {
+        url = gIOS.newURI(urlspec, null, manifestUri);
+
+        if (pageFilterRegexp && !pageFilterRegexp.test(url.spec))
+          continue;
 
-      if (pageFilterRegexp && !pageFilterRegexp.test(url.spec))
-        continue;
+        url_array.push({ url, flags });
+      } else {
+        // base vs ref type of talos test
+        // we add a 'pre' prefix here indicating that this particular page is a base page or a reference
+        // page; later on this 'pre' is used when recording the actual time value/result; because in
+        // the results we use the url as the results key; but we might use the same test page as a reference
+        // page in the same test suite, so we need to add a prefix so this results key is always unique
+        url = gIOS.newURI(urlspecBase, null, manifestUri);
+        if (pageFilterRegexp && !pageFilterRegexp.test(url.spec))
+          continue;
+        var pre = "base_page_" + baseVsRefIndex + "_";
+        url_array.push({ url, flags, pre });
 
-      d.push({   url,
-               flags });
+        url = gIOS.newURI(urlspecRef, null, manifestUri);
+        if (pageFilterRegexp && !pageFilterRegexp.test(url.spec))
+          continue;
+        pre = "ref_page_" + baseVsRefIndex + "_";
+        url_array.push({ url, flags, pre });
+      }
     }
   } while (more);
 
-  return d;
+  return url_array;
 }
 
 function dumpLine(str) {
   if (MozillaFileLogger && MozillaFileLogger._foStream)
     MozillaFileLogger.log(str + "\n");
   dump(str);
   dump("\n");
 }
--- a/testing/talos/talos/pageloader/install.rdf
+++ b/testing/talos/talos/pageloader/install.rdf
@@ -1,15 +1,15 @@
 <?xml version="1.0"?>
 
 <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
      xmlns:em="http://www.mozilla.org/2004/em-rdf#">
   <Description about="urn:mozilla:install-manifest">
     <em:id>pageloader@mozilla.org</em:id>
-    <em:version>1.0.27</em:version>
+    <em:version>1.0.29</em:version>
     <em:targetApplication>
       <Description>
         <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
         <em:minVersion>44.0</em:minVersion>
         <em:maxVersion>*</em:maxVersion>
       </Description>
     </em:targetApplication>
     <!-- Front End MetaData -->
index 2c2526e3c9c8b59b88b649908a88a39ef7584b2a..41d7a39d83fc428b9c3a3e018159cd0345a34430
GIT binary patch
literal 31836
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
--- a/testing/talos/talos/results.py
+++ b/testing/talos/talos/results.py
@@ -248,17 +248,22 @@ class PageloaderResults(Results):
             self.results.append(result)
 
     def format_pagename(self, page):
         """
         fix up the page for reporting
         """
         page = page.rstrip('/')
         if '/' in page:
-            page = page.split('/')[0]
+            if 'base_page' in page or 'ref_page' in page:
+                # for base vs ref type test, the page name is different format, i.e.
+                # base_page_1_http://localhost:53309/tests/perf-reftest/bloom-basic.html
+                page = page.split('/')[-1]
+            else:
+                page = page.split('/')[0]
         return page
 
 
 class BrowserLogResults(object):
     """parse the results from the browser log output"""
 
     # tokens for the report types
     report_tokens = [
--- a/testing/talos/talos/run_tests.py
+++ b/testing/talos/talos/run_tests.py
@@ -336,39 +336,55 @@ def make_comparison_result(base_and_refe
     results object with the comparison results, that will look like traditional single test results
     like this:
 
     PERFHERDER_DATA: {"framework": {"name": "talos"}, "suites": [{"lowerIsBetter": true,
     "subtests": [{"name": "", "lowerIsBetter": true, "alertThreshold": 5.0, "replicates":
     [16.705, ...], "value": 16.705, "unit": "ms"}], "extraOptions": ["e10s"], "name":
     "bloom_basic", "alertThreshold": 5.0}]}
     '''
-    # separate the 'base' and 'reference' result run values
-    base_result_runs = base_and_reference_results.results[0].results[0]['runs']
-    ref_result_runs = base_and_reference_results.results[0].results[1]['runs']
-
     # create a new results object for the comparison result; keep replicates from both pages
     comparison_result = copy.deepcopy(base_and_reference_results)
 
     # remove original results from our copy as they will be replaced by one comparison result
     comparison_result.results[0].results = []
+    comp_results = comparison_result.results[0].results
 
-    # populate our new comparison result with 'base' and 'ref' replicates
-    comparison_result.results[0].results.append({'index': 0,
-                                                 'runs': [],
-                                                 'page': '',
-                                                 'base_runs': base_result_runs,
-                                                 'ref_runs': ref_result_runs})
+    # zero-based count of how many base vs reftest sets we have
+    subtest_index = 0
+
+    # each set of two results is actually a base test followed by the
+    # reference test; we want to go through each set of base vs reference
+    for x in range(0, len(base_and_reference_results.results[0].results), 2):
+
+        # separate the 'base' and 'reference' result run values
+        results = base_and_reference_results.results[0].results
+        base_result_runs = results[x]['runs']
+        ref_result_runs = results[x + 1]['runs']
+
+        # the test/subtest result is the difference between the base vs reference test page
+        # values; for this result use the base test page name for the subtest/test name
+        sub_test_name = base_and_reference_results.results[0].results[x]['page']
 
-    # now step thru each result, compare 'base' vs 'ref', and store the difference in 'runs'
-    _index = 0
-    for next_ref in comparison_result.results[0].results[0]['ref_runs']:
-        diff = abs(next_ref - comparison_result.results[0].results[0]['base_runs'][_index])
-        comparison_result.results[0].results[0]['runs'].append(round(diff, 3))
-        _index += 1
+        # populate our new comparison result with 'base' and 'ref' replicates
+        comp_results.append({'index': 0,
+                             'runs': [],
+                             'page': sub_test_name,
+                             'base_runs': base_result_runs,
+                             'ref_runs': ref_result_runs})
+
+        # now step thru each result, compare 'base' vs 'ref', and store the difference in 'runs'
+        _index = 0
+        for next_ref in comp_results[subtest_index]['ref_runs']:
+            diff = abs(next_ref - comp_results[subtest_index]['base_runs'][_index])
+            comp_results[subtest_index]['runs'].append(round(diff, 3))
+            _index += 1
+
+        # increment our base vs reference subtest index
+        subtest_index += 1
 
     return comparison_result
 
 
 def convert_to_separate_test_results(multi_value_result, test_event_map):
     ''' Receive a test result that actually contains multiple values in a single iteration, and
     parse it out in order to 'fake' three seprate test results.
 
--- a/testing/talos/talos/test.py
+++ b/testing/talos/talos/test.py
@@ -802,24 +802,24 @@ class a11yr(PageloaderTest):
     tpmozafterpaint = True
     tpchrome = False
     preferences = {'dom.send_after_paint_to_content': False}
     unit = 'ms'
     alert_threshold = 5.0
 
 
 @register_test()
-class bloom_basic(PageloaderTest):
+class perf_reftest(PageloaderTest):
     """
-    Stylo bloom_basic: runs bloom_basic and bloom_basic_ref and reports difference
+    Style perf-reftest a set of tests where the result is the difference of base vs ref pages
     """
     base_vs_ref = True  # compare the two test pages with eachother and report comparison
-    tpmanifest = '${talos}/tests/perf-reftest/bloom_basic.manifest'
+    tpmanifest = '${talos}/tests/perf-reftest/perf_reftest.manifest'
     tpcycles = 1
-    tppagecycles = 25
+    tppagecycles = 10
     gecko_profile_interval = 1
     gecko_profile_entries = 2000000
     filters = filter.ignore_first.prepare(5) + filter.median.prepare()
     unit = 'ms'
     lower_is_better = True
     alert_threshold = 5.0
 
 
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/perf-reftest/.eslintrc.json
@@ -0,0 +1,6 @@
+{
+    "rules": {
+        "no-undef": "off"
+    }
+}
+
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/perf-reftest/bloom-basic-2.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <script src="util.js"></script>
+    <script>
+window.onload = function() {
+  /* Use many rules, instead of one rule with many selectors, to test per-rule overhead. */
+  document.head.appendChild(build_rule("caption div, caption span", 1, "{ color: blue; } ", 20000));
+  let dom = build_dom(5000, "div");
+
+  flush_style();
+  perf_start();
+  document.body.appendChild(dom);
+  flush_style(dom);
+  perf_finish();
+}
+    </script>
+  </head>
+  <body>
+  </body>
+</html>
--- a/testing/talos/talos/tests/perf-reftest/bloom-basic-ref.html
+++ b/testing/talos/talos/tests/perf-reftest/bloom-basic-ref.html
@@ -1,34 +1,20 @@
 <!DOCTYPE html>
 <html>
   <head>
     <script src="util.js"></script>
-    <script src="chrome://talos-powers-content/content/TalosContentProfiler.js"></script>
     <script>
-/* import-globals-from util.js */
 window.onload = function() {
-  document.head.appendChild(build_rule("span > div", 10000, "{ color: blue; } "));
+  document.head.appendChild(build_rule("caption > div, caption > span", 20000, "{ color: blue; } "));
   let dom = build_dom(5000, "div");
 
-  TalosContentProfiler.resume("bloom_basic_ref start", true).then(() => {
-    let start = performance.now();
-    document.body.appendChild(dom);
-    window.foo = window.getComputedStyle(document.body).color;
-    let end = performance.now();
-
-    TalosContentProfiler.pause("bloom_basic_ref finish", true).then(() => {
-      // when running in talos report results; when running outside talos just alert
-      if (window.tpRecordTime) {
-        window.tpRecordTime(end - start, start);
-      } else {
-        console.log(end);
-        console.log(start);
-        alert("Result: " + (end - start).toFixed(2) + " (ms)");
-      }
-    });
-  });
+  flush_style();
+  perf_start();
+  document.body.appendChild(dom);
+  flush_style(dom);
+  perf_finish();
 }
     </script>
   </head>
   <body>
   </body>
 </html>
--- a/testing/talos/talos/tests/perf-reftest/bloom-basic.html
+++ b/testing/talos/talos/tests/perf-reftest/bloom-basic.html
@@ -1,34 +1,20 @@
 <!DOCTYPE html>
 <html>
   <head>
     <script src="util.js"></script>
-    <script src="chrome://talos-powers-content/content/TalosContentProfiler.js"></script>
     <script>
-/* import-globals-from util.js */
 window.onload = function() {
-  document.head.appendChild(build_rule("span div", 10000, "{ color: blue; } "));
+  document.head.appendChild(build_rule("caption div, caption span", 20000, "{ color: blue; } "));
   let dom = build_dom(5000, "div");
 
-  TalosContentProfiler.resume("bloom_basic start", true).then(() => {
-    let start = performance.now();
-    document.body.appendChild(dom);
-    window.foo = window.getComputedStyle(document.body).color;
-    let end = performance.now();
-
-    TalosContentProfiler.pause("bloom_basic end", true).then(() => {
-      // when running in talos report results; when running outside talos just alert
-      if (window.tpRecordTime) {
-        window.tpRecordTime(end - start, start);
-      } else {
-        console.log(end);
-        console.log(start);
-        alert("Result: " + (end - start).toFixed(2) + " (ms)");
-      }
-    });
-  });
+  flush_style();
+  perf_start();
+  document.body.appendChild(dom);
+  flush_style(dom);
+  perf_finish();
 }
     </script>
   </head>
   <body>
   </body>
 </html>
deleted file mode 100644
--- a/testing/talos/talos/tests/perf-reftest/bloom_basic.manifest
+++ /dev/null
@@ -1,4 +0,0 @@
-# base_vs_ref is set in test.py for this test, so each of these pages are run as separate
-# tests, but then compared against eachother; and the reported results are the comparison
-% http://localhost/tests/perf-reftest/bloom-basic.html
-% http://localhost/tests/perf-reftest/bloom-basic-ref.html
deleted file mode 100644
--- a/testing/talos/talos/tests/perf-reftest/bloom_basic_ref.manifest
+++ /dev/null
@@ -1,1 +0,0 @@
-% http://localhost/tests/perf-reftest/bloom-basic-ref.html
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/perf-reftest/coalesce-1.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<style>
+.x { color: yellow; }
+</style>
+<script src="util.js"></script>
+<script>
+function set_class(n) {
+  n.className = "x";
+  n = n.firstChild;
+  while (n) {
+    set_class(n);
+    n = n.nextSibling;
+  }
+}
+window.onload = function() {
+  let root = build_dom(50000, "div");
+  document.body.appendChild(root);
+  flush_style(root);
+  perf_start();
+  set_class(root);
+  flush_style(root);
+  perf_finish();
+};
+</script>
+<body></body>
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/perf-reftest/coalesce-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<style>
+.x, .x * { color: yellow; }
+</style>
+<script src="util.js"></script>
+<script>
+window.onload = function() {
+  let root = build_dom(50000, "div");
+  document.body.appendChild(root);
+  flush_style(root);
+  root.className = "x";
+  perf_start();
+  flush_style(root);
+  perf_finish();
+};
+</script>
+<body></body>
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/perf-reftest/perf_reftest.manifest
@@ -0,0 +1,6 @@
+# base_vs_ref is set in test.py for this test, so each of these lines is the base vs ref test pag
+# both pages are run and then the results compared, the ultimate reported results are the comparisons.
+# Each line is reported as a subtest like the other talos tests that have multiple lines of URLs.
+& http://localhost/tests/perf-reftest/bloom-basic.html, http://localhost/tests/perf-reftest/bloom-basic-ref.html
+& http://localhost/tests/perf-reftest/bloom-basic-2.html, http://localhost/tests/perf-reftest/bloom-basic-ref.html
+& http://localhost/tests/perf-reftest/coalesce-1.html, http://localhost/tests/perf-reftest/coalesce-ref.html
--- a/testing/talos/talos/tests/perf-reftest/util.js
+++ b/testing/talos/talos/tests/perf-reftest/util.js
@@ -1,17 +1,82 @@
-function build_dom(n, elemName) {
+var perf_data = {
+  start: null,
+  end: null,
+}
+
+function build_dom(n, elemName, options) {
+  // By default we use different elements in the DOM to defeat the style sharing
+  // cache, otherwise this sythetic DOM is trivially stylable by engines with that
+  // optimization.
+  options = options || {};
+  var elemNameLeft = options.elemNameLeft || "div";
+  var elemNameRight = options.elemNameRight || "span";
+
   var ours = document.createElement(elemName);
+  for (var attr in options.attributes) {
+    ours.setAttribute(attr, options.attributes[attr]);
+  }
+
   if (n != 1) {
     var leftSize = Math.floor(n / 2);
     var rightSize = Math.floor((n - 1) / 2);
-    ours.appendChild(build_dom(leftSize, elemName));
+    ours.appendChild(build_dom(leftSize, elemNameLeft, options));
     if (rightSize > 0)
-      ours.appendChild(build_dom(rightSize, elemName));
+      ours.appendChild(build_dom(rightSize, elemNameRight, options));
   }
   return ours;
 }
 
-function build_rule(selector, selectorRepeat, declaration) {
+function build_rule(selector, selectorRepeat, declaration, ruleRepeat) {
+  ruleRepeat = ruleRepeat || 1;
   var s = document.createElement("style");
-  s.textContent = Array(selectorRepeat).fill(selector).join(", ") + declaration;
+  var rule = Array(selectorRepeat).fill(selector).join(", ") + declaration;
+  s.textContent = Array(ruleRepeat).fill(rule).join("\n\n");
   return s;
 }
+
+function flush_style(element) {
+  getComputedStyle(element || document.documentElement).color;
+}
+
+function perf_start() {
+  if (perf_data.start !== null) {
+    throw "already started timing!";
+  }
+
+  perf_data.start = performance.now();
+}
+
+function perf_finish() {
+  var end = performance.now();
+
+  if (perf_data.start === null) {
+    throw "haven't started timing!";
+  }
+
+  if (perf_data.end !== null) {
+    throw "already finished timing!";
+  }
+
+  var start = perf_data.start;
+  perf_data.end = end;
+
+  // when running in talos report results; when running outside talos just alert
+  if (window.tpRecordTime) {
+    // Running in talos.
+    window.tpRecordTime(end - start, start);
+  } else if (window.parent && window.parent.report_perf_reftest_time) {
+    // Running in the perf-reftest runner.
+    window.parent.report_perf_reftest_time({ type: "time", value: end - start });
+  } else {
+    // Running standalone; just alert.
+    console.log(end);
+    console.log(start);
+    alert("Result: " + (end - start).toFixed(2) + " (ms)");
+  }
+}
+
+if (window.parent.report_perf_reftest_time) {
+  window.addEventListener("error", function(e) {
+    window.parent.report_perf_reftest_time({ type: "error", value: e.message });
+  });
+}