| # 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 json |
| import logging |
| |
| from metrics import histogram_util |
| from metrics import Metric |
| from telemetry.core import util |
| |
| |
| class StartupMetric(Metric): |
| """A metric for browser startup time. |
| |
| User visible metrics: |
| process_creation_to_window_display: Time from browser process creation to |
| the time that the browser window initially becomes visible. |
| process_creation_to_foreground_tab_loaded: Time from browser process |
| creation to the time that the foreground tab is fully loaded. |
| process_creation_to_all_tabs_loaded: Time from the browser process creation |
| to the time that all tabs have fully loaded. |
| |
| Critical code progression: |
| process_creation_to_main: Time from process creation to the execution of the |
| browser's main() entry. |
| main_to_messageloop_start: Time from main() entry to the start of the UI |
| thread's message loop. |
| """ |
| |
| 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.""" |
| high_bytes = histogram_util.GetHistogramSum( |
| histogram_util.BROWSER_HISTOGRAM, |
| 'Startup.BrowserMainEntryTimeAbsoluteHighWord', |
| tab) |
| low_bytes = histogram_util.GetHistogramSum( |
| histogram_util.BROWSER_HISTOGRAM, |
| 'Startup.BrowserMainEntryTimeAbsoluteLowWord', |
| tab) |
| if high_bytes == 0 and low_bytes == 0: |
| return None |
| return (int(high_bytes) << 32) | (int(low_bytes) << 1) |
| |
| def _GetTabLoadTimes(self, browser): |
| """Returns a tuple of (foreground_tab_load_time, all_tabs_load_time).""" |
| foreground_tab_load_time = 0 |
| all_tabs_load_time = 0 |
| for i in xrange(len(browser.tabs)): |
| try: |
| tab = browser.tabs[i] |
| tab_load_timing_js = 'statsCollectionController.tabLoadTiming()' |
| def HasLoaded(): |
| result = json.loads(tab.EvaluateJavaScript(tab_load_timing_js)) |
| return 'load_duration_ms' in result and result['load_duration_ms'] |
| util.WaitFor(HasLoaded, 60) |
| result = json.loads(tab.EvaluateJavaScript(tab_load_timing_js)) |
| load_time = result['load_start_ms'] + result['load_duration_ms'] |
| all_tabs_load_time = max(all_tabs_load_time, load_time) |
| if tab == browser.foreground_tab: |
| foreground_tab_load_time = load_time |
| 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 timed out on JavaScript access') |
| return foreground_tab_load_time, all_tabs_load_time |
| |
| def AddResults(self, tab, results): |
| absolute_browser_main_entry_ms = self._GetBrowserMainEntryTime(tab) |
| |
| process_creation_to_window_display_ms = histogram_util.GetHistogramSum( |
| histogram_util.BROWSER_HISTOGRAM, 'Startup.BrowserWindowDisplay', tab) |
| absolute_foreground_tab_loaded_ms, absolute_all_tabs_loaded_ms = \ |
| self._GetTabLoadTimes(tab.browser) |
| process_creation_to_messageloop_start_ms = histogram_util.GetHistogramSum( |
| histogram_util.BROWSER_HISTOGRAM, 'Startup.BrowserMessageLoopStartTime', |
| tab) |
| main_to_messageloop_start_ms = histogram_util.GetHistogramSum( |
| histogram_util.BROWSER_HISTOGRAM, |
| 'Startup.BrowserMessageLoopStartTimeFromMainEntry', |
| tab) |
| process_creation_to_main = (process_creation_to_messageloop_start_ms - |
| main_to_messageloop_start_ms) |
| |
| # User visible. |
| results.Add('process_creation_to_window_display', 'ms', |
| process_creation_to_window_display_ms) |
| results.Add('process_creation_to_foreground_tab_loaded', 'ms', |
| absolute_foreground_tab_loaded_ms - |
| absolute_browser_main_entry_ms + process_creation_to_main) |
| results.Add('process_creation_to_all_tabs_loaded', 'ms', |
| absolute_all_tabs_loaded_ms - |
| absolute_browser_main_entry_ms + process_creation_to_main) |
| |
| # Critical code progression. |
| results.Add('process_creation_to_main', 'ms', |
| process_creation_to_main) |
| results.Add('main_to_messageloop_start', 'ms', |
| main_to_messageloop_start_ms) |