Index: tools/perf/measurements/timeline_based_measurement.py |
diff --git a/tools/perf/measurements/timeline_based_measurement.py b/tools/perf/measurements/timeline_based_measurement.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a9e1ecc78bf3d3bc990d03c1e578ffec3b31ffc6 |
--- /dev/null |
+++ b/tools/perf/measurements/timeline_based_measurement.py |
@@ -0,0 +1,110 @@ |
+# Copyright 2014 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+from metrics import timeline as timeline_module |
+from metrics import timeline_interaction_record as tir_module |
+from telemetry.page import page_measurement |
+from telemetry.core.timeline import model as model_module |
+ |
+ |
+ |
+# TimelineBasedMeasurement considers all instrumentation as producing a single |
+# timeline. But, depending on the amount of instrumentation that is enabled, |
+# overhead increases. The user of the measurement must therefore chose between |
+# a few levels of instrumentation. |
+NO_OVERHEAD_LEVEL = 'no-overhead' |
+MINIMAL_OVERHEAD_LEVEL = 'minimal-overhead' |
+DEBUG_OVERHEAD_LEVEL = 'debug-overhead' |
+ |
+ALL_OVERHEAD_LEVELS = [ |
+ NO_OVERHEAD_LEVEL, |
+ MINIMAL_OVERHEAD_LEVEL, |
+ DEBUG_OVERHEAD_LEVEL |
+] |
+ |
+ |
+class _TimelineBasedMetrics(object): |
+ def __init__(self, model, renderer_thread): |
+ self._model = model |
+ self._renderer_thread = renderer_thread |
+ |
+ def FindTimelineInteractionRecords(self): |
+ # TODO(nduca): Add support for page-load interaction record. |
+ return [tir_module.TimelineInteractionRecord(event) for |
+ event in self._renderer_thread.IterAllAsyncSlices() |
+ if tir_module.IsTimelineInteractionRecord(event.name)] |
+ |
+ def CreateMetricsForTimelineInteractionRecord(self, interaction): |
+ res = [] |
+ if interaction.is_smooth: |
+ pass # TODO(nduca): res.append smoothness metric instance. |
+ return res |
+ |
+ def AddResults(self, results): |
+ interactions = self.FindTimelineInteractionRecords() |
+ if len(interactions) == 0: |
+ raise Exception('Expected at least one Interaction on the page') |
+ for interaction in interactions: |
+ metrics = self.CreateMetricsForTimelineInteractionRecord(interaction) |
+ for m in metrics: |
+ m.AddResults(self._model, self._renderer_thread, |
+ interaction, results) |
+ |
+ |
+class TimelineBasedMeasurement(page_measurement.PageMeasurement): |
+ """Collects multiple metrics pages based on their interaction records. |
+ |
+ A timeline measurement shifts the burden of what metrics to collect onto the |
+ page under test, or the pageset running that page. Instead of the measurement |
+ having a fixed set of values it collects about the page, the page being tested |
+ issues (via javascript) an Interaction record into the user timing API that |
+ describing what the page is doing at that time, as well as a standardized set |
+ of flags describing the semantics of the work being done. The |
+ TimelineBasedMeasurement object collects a trace that includes both these |
+ interaction recorsd, and a user-chosen amount of performance data using |
+ Telemetry's various timeline-producing APIs, tracing especially. |
+ |
+ It then passes the recorded timeline to different TimelineBasedMetrics based |
+ on those flags. This allows a single run through a page to produce load timing |
+ data, smoothness data, critical jank information and overall cpu usage |
+ information. |
+ |
+ For information on how to mark up a page to work with |
+ TimelineBasedMeasurement, refer to the |
+ perf.metrics.timeline_interaction_record module. |
+ |
+ """ |
+ def __init__(self): |
+ super(TimelineBasedMeasurement, self).__init__('smoothness') |
+ |
+ def AddCommandLineOptions(self, parser): |
+ parser.add_option( |
+ '--overhead-level', type='choice', |
+ choices=ALL_OVERHEAD_LEVELS, |
+ default=NO_OVERHEAD_LEVEL, |
+ help='How much overhead to incur during the measurement.') |
+ |
+ def CanRunForPage(self, page): |
+ return hasattr(page, 'smoothness') |
+ |
+ def WillNavigateToPage(self, page, tab): |
+ if not tab.browser.supports_tracing: |
+ raise Exception('Not supported') |
+ assert self.options.overhead_level in ALL_OVERHEAD_LEVELS |
+ if self.options.overhead_level == NO_OVERHEAD_LEVEL: |
+ categories = timeline_module.MINIMAL_TRACE_CATEGORIES |
+ elif self.options.overhead_level == \ |
+ MINIMAL_OVERHEAD_LEVEL: |
+ categories = '' |
+ else: |
+ categories = '*,disabled-by-default-cc.debug' |
+ tab.browser.StartTracing(categories) |
+ |
+ def MeasurePage(self, page, tab, results): |
+ """ Collect all possible metrics and added them to results. """ |
+ trace_result = tab.browser.StopTracing() |
+ model = model_module.TimelineModel(trace_result) |
+ renderer_thread = model.GetRendererThreadFromTab(tab) |
+ meta_metrics = _TimelineBasedMetrics(model, renderer_thread) |
+ meta_metrics.AddResults(results) |