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