普通文本  |  133行  |  4.83 KB

# Copyright 2013 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.
import collections
import json
import logging

from metrics import Metric
from metrics import histogram_util

from telemetry.core import util


class StartupMetric(Metric):
  "A metric for browser startup time."

  HISTOGRAMS_TO_RECORD = {
    'messageloop_start_time' :
        'Startup.BrowserMessageLoopStartTimeFromMainEntry',
    'window_display_time' : 'Startup.BrowserWindowDisplay',
    'open_tabs_time' : 'Startup.BrowserOpenTabs'}

  def Start(self, page, tab):
    raise NotImplementedError()

  def Stop(self, page, tab):
    raise NotImplementedError()

  def _GetBrowserMainEntryTime(self, tab):
    """Returns the main entry time (in ms) of the browser."""
    histogram_type = histogram_util.BROWSER_HISTOGRAM
    high_bytes = histogram_util.GetHistogramSum(
        histogram_type,
        'Startup.BrowserMainEntryTimeAbsoluteHighWord',
        tab)
    low_bytes = histogram_util.GetHistogramSum(
        histogram_type,
        'Startup.BrowserMainEntryTimeAbsoluteLowWord',
        tab)
    if high_bytes == 0 and low_bytes == 0:
      return None
    return (int(high_bytes) << 32) | (int(low_bytes) << 1)

  # pylint: disable=W0101
  def _RecordTabLoadTimes(self, tab, browser_main_entry_time_ms, results):
    """Records the tab load times for the browser. """
    tab_load_times = []
    TabLoadTime = collections.namedtuple(
        'TabLoadTime',
        ['load_start_ms', 'load_duration_ms', 'is_foreground_tab'])
    num_open_tabs = len(tab.browser.tabs)
    for i in xrange(num_open_tabs):
      try:
        t = tab.browser.tabs[i]
        t.WaitForDocumentReadyStateToBeComplete()

        result = t.EvaluateJavaScript(
            'statsCollectionController.tabLoadTiming()')
        result = json.loads(result)

        if 'load_start_ms' not in result or 'load_duration_ms' not in result:
          raise Exception("Outdated Chrome version, "
              "statsCollectionController.tabLoadTiming() not present")
          return
        if result['load_duration_ms'] is None:
          tab_title = t.EvaluateJavaScript('document.title')
          print "Page: ", tab_title, " didn't finish loading."
          continue

        is_foreground_tab = t.EvaluateJavaScript('!document.hidden')
        tab_load_times.append(TabLoadTime(
            int(result['load_start_ms']),
            int(result['load_duration_ms']),
            is_foreground_tab))
      except util.TimeoutException:
        # Low memory Android devices may not be able to load more than
        # one tab at a time, so may timeout when the test attempts to
        # access a background tab. Ignore these tabs.
        logging.error("Tab number: %d timed out on JavaScript access" % i)
        continue

    # Postprocess results
    load_complete_times = (
        [t.load_start_ms + t.load_duration_ms for t in tab_load_times])
    load_complete_times.sort()

    if 'android' in tab.browser.browser_type:
      # document.hidden is broken on Android - crbug.com/322544.
      foreground_tab_stats = [tab_load_times[0]]
    else:
      foreground_tab_stats = (
          [t for t in tab_load_times if t.is_foreground_tab == True])
    if (len(foreground_tab_stats) != 1):
      raise Exception ("More than one foreground tab? ", foreground_tab_stats)
    foreground_tab_stats = foreground_tab_stats[0]

    # Report load stats.
    foreground_tab_load_complete = ((foreground_tab_stats.load_start_ms +
        foreground_tab_stats.load_duration_ms) - browser_main_entry_time_ms)

    results.Add(
        'foreground_tab_load_complete', 'ms', foreground_tab_load_complete)

    if num_open_tabs > 1:
      last_tab_load_complete = (
          load_complete_times[-1] - browser_main_entry_time_ms)
      results.Add('last_tab_load_complete', 'ms', last_tab_load_complete)

  def AddResults(self, tab, results):
    get_histogram_js = 'statsCollectionController.getBrowserHistogram("%s")'

    for display_name, histogram_name in self.HISTOGRAMS_TO_RECORD.iteritems():
      result = tab.EvaluateJavaScript(get_histogram_js % histogram_name)
      result = json.loads(result)
      measured_time = 0

      if 'sum' in result:
        # For all the histograms logged here, there's a single entry so sum
        # is the exact value for that entry.
        measured_time = result['sum']
      elif 'buckets' in result:
        measured_time = \
            (result['buckets'][0]['high'] + result['buckets'][0]['low']) / 2

      results.Add(display_name, 'ms', measured_time)

    # Get tab load times.
    browser_main_entry_time_ms = self._GetBrowserMainEntryTime(tab)
    if (browser_main_entry_time_ms is None):
      print "Outdated Chrome version, browser main entry time not supported."
      return
    self._RecordTabLoadTimes(tab, browser_main_entry_time_ms, results)