startup_metric.py revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1# Copyright 2013 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.
4import collections
5import json
6import logging
7
8from metrics import Metric
9from metrics import histogram_util
10
11from telemetry.core import util
12
13
14class StartupMetric(Metric):
15  "A metric for browser startup time."
16
17  HISTOGRAMS_TO_RECORD = {
18    'messageloop_start_time' :
19        'Startup.BrowserMessageLoopStartTimeFromMainEntry',
20    'window_display_time' : 'Startup.BrowserWindowDisplay',
21    'open_tabs_time' : 'Startup.BrowserOpenTabs'}
22
23  def Start(self, page, tab):
24    raise NotImplementedError()
25
26  def Stop(self, page, tab):
27    raise NotImplementedError()
28
29  def _GetBrowserMainEntryTime(self, tab):
30    """Returns the main entry time (in ms) of the browser."""
31    histogram_type = histogram_util.BROWSER_HISTOGRAM
32    high_bytes = histogram_util.GetHistogramSum(
33        histogram_type,
34        'Startup.BrowserMainEntryTimeAbsoluteHighWord',
35        tab)
36    low_bytes = histogram_util.GetHistogramSum(
37        histogram_type,
38        'Startup.BrowserMainEntryTimeAbsoluteLowWord',
39        tab)
40    if high_bytes == 0 and low_bytes == 0:
41      return None
42    return (int(high_bytes) << 32) | (int(low_bytes) << 1)
43
44  def _RecordTabLoadTimes(self, tab, browser_main_entry_time_ms, results):
45    """Records the tab load times for the browser. """
46    tab_load_times = []
47    TabLoadTime = collections.namedtuple(
48        'TabLoadTime',
49        ['load_start_ms', 'load_duration_ms'])
50
51    def RecordTabLoadTime(t):
52      try:
53        t.WaitForDocumentReadyStateToBeComplete()
54
55        result = t.EvaluateJavaScript(
56            'statsCollectionController.tabLoadTiming()')
57        result = json.loads(result)
58
59        if 'load_start_ms' not in result or 'load_duration_ms' not in result:
60          raise Exception("Outdated Chrome version, "
61              "statsCollectionController.tabLoadTiming() not present")
62        if result['load_duration_ms'] is None:
63          tab_title = t.EvaluateJavaScript('document.title')
64          print "Page: ", tab_title, " didn't finish loading."
65          return
66
67        tab_load_times.append(TabLoadTime(
68            int(result['load_start_ms']),
69            int(result['load_duration_ms'])))
70      except util.TimeoutException:
71        # Low memory Android devices may not be able to load more than
72        # one tab at a time, so may timeout when the test attempts to
73        # access a background tab. Ignore these tabs.
74        logging.error("Tab timed out on JavaScript access")
75
76    # Only measure the foreground tab. We can't measure all tabs on Android
77    # because on Android the data of the background tabs is loaded on demand,
78    # when the user switches to them, rather than during startup. In view of
79    # this, to get the same measures on all platform, we only measure the
80    # foreground tab on all platforms.
81
82    RecordTabLoadTime(tab.browser.foreground_tab)
83
84    foreground_tab_stats = tab_load_times[0]
85    foreground_tab_load_complete = ((foreground_tab_stats.load_start_ms +
86        foreground_tab_stats.load_duration_ms) - browser_main_entry_time_ms)
87    results.Add(
88        'foreground_tab_load_complete', 'ms', foreground_tab_load_complete)
89
90  def AddResults(self, tab, results):
91    get_histogram_js = 'statsCollectionController.getBrowserHistogram("%s")'
92
93    for display_name, histogram_name in self.HISTOGRAMS_TO_RECORD.iteritems():
94      result = tab.EvaluateJavaScript(get_histogram_js % histogram_name)
95      result = json.loads(result)
96      measured_time = 0
97
98      if 'sum' in result:
99        # For all the histograms logged here, there's a single entry so sum
100        # is the exact value for that entry.
101        measured_time = result['sum']
102      elif 'buckets' in result:
103        measured_time = \
104            (result['buckets'][0]['high'] + result['buckets'][0]['low']) / 2
105
106      results.Add(display_name, 'ms', measured_time)
107
108    # Get tab load times.
109    browser_main_entry_time_ms = self._GetBrowserMainEntryTime(tab)
110    if (browser_main_entry_time_ms is None):
111      print "Outdated Chrome version, browser main entry time not supported."
112      return
113    self._RecordTabLoadTimes(tab, browser_main_entry_time_ms, results)
114