OLD | NEW |
(Empty) | |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 from metrics import timeline as timeline_module |
| 6 from metrics import timeline_interaction_record as tir_module |
| 7 from telemetry.page import page_measurement |
| 8 from telemetry.core.timeline import model as model_module |
| 9 |
| 10 |
| 11 |
| 12 # TimelineBasedMeasurement considers all instrumentation as producing a single |
| 13 # timeline. But, depending on the amount of instrumentation that is enabled, |
| 14 # overhead increases. The user of the measurement must therefore chose between |
| 15 # a few levels of instrumentation. |
| 16 NO_OVERHEAD_LEVEL = 'no-overhead' |
| 17 MINIMAL_OVERHEAD_LEVEL = 'minimal-overhead' |
| 18 DEBUG_OVERHEAD_LEVEL = 'debug-overhead' |
| 19 |
| 20 ALL_OVERHEAD_LEVELS = [ |
| 21 NO_OVERHEAD_LEVEL, |
| 22 MINIMAL_OVERHEAD_LEVEL, |
| 23 DEBUG_OVERHEAD_LEVEL |
| 24 ] |
| 25 |
| 26 |
| 27 class _TimelineBasedMetrics(object): |
| 28 def __init__(self, model, renderer_thread): |
| 29 self._model = model |
| 30 self._renderer_thread = renderer_thread |
| 31 |
| 32 def FindTimelineInteractionRecords(self): |
| 33 # TODO(nduca): Add support for page-load interaction record. |
| 34 return [tir_module.TimelineInteractionRecord(event) for |
| 35 event in self._renderer_thread.IterAllAsyncSlices() |
| 36 if tir_module.IsTimelineInteractionRecord(event.name)] |
| 37 |
| 38 def CreateMetricsForTimelineInteractionRecord(self, interaction): |
| 39 res = [] |
| 40 if interaction.is_smooth: |
| 41 pass # TODO(nduca): res.append smoothness metric instance. |
| 42 return res |
| 43 |
| 44 def AddResults(self, results): |
| 45 interactions = self.FindTimelineInteractionRecords() |
| 46 if len(interactions) == 0: |
| 47 raise Exception('Expected at least one Interaction on the page') |
| 48 for interaction in interactions: |
| 49 metrics = self.CreateMetricsForTimelineInteractionRecord(interaction) |
| 50 for m in metrics: |
| 51 m.AddResults(self._model, self._renderer_thread, |
| 52 interaction, results) |
| 53 |
| 54 |
| 55 class TimelineBasedMeasurement(page_measurement.PageMeasurement): |
| 56 """Collects multiple metrics pages based on their interaction records. |
| 57 |
| 58 A timeline measurement shifts the burden of what metrics to collect onto the |
| 59 page under test, or the pageset running that page. Instead of the measurement |
| 60 having a fixed set of values it collects about the page, the page being tested |
| 61 issues (via javascript) an Interaction record into the user timing API that |
| 62 describing what the page is doing at that time, as well as a standardized set |
| 63 of flags describing the semantics of the work being done. The |
| 64 TimelineBasedMeasurement object collects a trace that includes both these |
| 65 interaction recorsd, and a user-chosen amount of performance data using |
| 66 Telemetry's various timeline-producing APIs, tracing especially. |
| 67 |
| 68 It then passes the recorded timeline to different TimelineBasedMetrics based |
| 69 on those flags. This allows a single run through a page to produce load timing |
| 70 data, smoothness data, critical jank information and overall cpu usage |
| 71 information. |
| 72 |
| 73 For information on how to mark up a page to work with |
| 74 TimelineBasedMeasurement, refer to the |
| 75 perf.metrics.timeline_interaction_record module. |
| 76 |
| 77 """ |
| 78 def __init__(self): |
| 79 super(TimelineBasedMeasurement, self).__init__('smoothness') |
| 80 |
| 81 def AddCommandLineOptions(self, parser): |
| 82 parser.add_option( |
| 83 '--overhead-level', type='choice', |
| 84 choices=ALL_OVERHEAD_LEVELS, |
| 85 default=NO_OVERHEAD_LEVEL, |
| 86 help='How much overhead to incur during the measurement.') |
| 87 |
| 88 def CanRunForPage(self, page): |
| 89 return hasattr(page, 'smoothness') |
| 90 |
| 91 def WillNavigateToPage(self, page, tab): |
| 92 if not tab.browser.supports_tracing: |
| 93 raise Exception('Not supported') |
| 94 assert self.options.overhead_level in ALL_OVERHEAD_LEVELS |
| 95 if self.options.overhead_level == NO_OVERHEAD_LEVEL: |
| 96 categories = timeline_module.MINIMAL_TRACE_CATEGORIES |
| 97 elif self.options.overhead_level == \ |
| 98 MINIMAL_OVERHEAD_LEVEL: |
| 99 categories = '' |
| 100 else: |
| 101 categories = '*,disabled-by-default-cc.debug' |
| 102 tab.browser.StartTracing(categories) |
| 103 |
| 104 def MeasurePage(self, page, tab, results): |
| 105 """ Collect all possible metrics and added them to results. """ |
| 106 trace_result = tab.browser.StopTracing() |
| 107 model = model_module.TimelineModel(trace_result) |
| 108 renderer_thread = model.GetRendererThreadFromTab(tab) |
| 109 meta_metrics = _TimelineBasedMetrics(model, renderer_thread) |
| 110 meta_metrics.AddResults(results) |
OLD | NEW |