Bug 1397438 - Add subtests support for talos base vs ref pageloader tests; r?jmaher draft
authorRob Wood <rwood@mozilla.com>
Thu, 21 Sep 2017 08:47:56 -0400
changeset 668280 cbcf0864465448607cf2d99c8312be4a5902dc7a
parent 668025 47f7b6c64265bc7bdd22eef7ab71abc97cf3f8bf
child 732658 49083820ac8b8d0a046d4cc98d0e7801fb1c9097
push id80999
push userrwood@mozilla.com
push dateThu, 21 Sep 2017 12:50:49 +0000
reviewersjmaher
bugs1397438
milestone57.0a1
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 });
+  });
+}