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 5import json 6import logging 7 8from metrics import histogram_util 9from metrics import Metric 10from telemetry.core import util 11 12 13class StartupMetric(Metric): 14 """A metric for browser startup time. 15 16 User visible metrics: 17 process_creation_to_window_display: Time from browser process creation to 18 the time that the browser window initially becomes visible. 19 process_creation_to_foreground_tab_loaded: Time from browser process 20 creation to the time that the foreground tab is fully loaded. 21 process_creation_to_all_tabs_loaded: Time from the browser process creation 22 to the time that all tabs have fully loaded. 23 24 Critical code progression: 25 process_creation_to_main: Time from process creation to the execution of the 26 browser's main() entry. 27 main_to_messageloop_start: Time from main() entry to the start of the UI 28 thread's message loop. 29 """ 30 31 def Start(self, page, tab): 32 raise NotImplementedError() 33 34 def Stop(self, page, tab): 35 raise NotImplementedError() 36 37 def _GetBrowserMainEntryTime(self, tab): 38 """Returns the main entry time (in ms) of the browser.""" 39 high_bytes = histogram_util.GetHistogramSum( 40 histogram_util.BROWSER_HISTOGRAM, 41 'Startup.BrowserMainEntryTimeAbsoluteHighWord', 42 tab) 43 low_bytes = histogram_util.GetHistogramSum( 44 histogram_util.BROWSER_HISTOGRAM, 45 'Startup.BrowserMainEntryTimeAbsoluteLowWord', 46 tab) 47 if high_bytes == 0 and low_bytes == 0: 48 return None 49 return (int(high_bytes) << 32) | (int(low_bytes) << 1) 50 51 def _GetTabLoadTimes(self, browser): 52 """Returns a tuple of (foreground_tab_load_time, all_tabs_load_time).""" 53 foreground_tab_load_time = 0 54 all_tabs_load_time = 0 55 for i in xrange(len(browser.tabs)): 56 try: 57 tab = browser.tabs[i] 58 tab_load_timing_js = 'statsCollectionController.tabLoadTiming()' 59 def HasLoaded(): 60 result = json.loads(tab.EvaluateJavaScript(tab_load_timing_js)) 61 return 'load_duration_ms' in result and result['load_duration_ms'] 62 util.WaitFor(HasLoaded, 60) 63 result = json.loads(tab.EvaluateJavaScript(tab_load_timing_js)) 64 load_time = result['load_start_ms'] + result['load_duration_ms'] 65 all_tabs_load_time = max(all_tabs_load_time, load_time) 66 if tab == browser.foreground_tab: 67 foreground_tab_load_time = load_time 68 except util.TimeoutException: 69 # Low memory Android devices may not be able to load more than 70 # one tab at a time, so may timeout when the test attempts to 71 # access a background tab. Ignore these tabs. 72 logging.error('Tab timed out on JavaScript access') 73 return foreground_tab_load_time, all_tabs_load_time 74 75 def AddResults(self, tab, results): 76 absolute_browser_main_entry_ms = self._GetBrowserMainEntryTime(tab) 77 78 process_creation_to_window_display_ms = histogram_util.GetHistogramSum( 79 histogram_util.BROWSER_HISTOGRAM, 'Startup.BrowserWindowDisplay', tab) 80 absolute_foreground_tab_loaded_ms, absolute_all_tabs_loaded_ms = \ 81 self._GetTabLoadTimes(tab.browser) 82 process_creation_to_messageloop_start_ms = histogram_util.GetHistogramSum( 83 histogram_util.BROWSER_HISTOGRAM, 'Startup.BrowserMessageLoopStartTime', 84 tab) 85 main_to_messageloop_start_ms = histogram_util.GetHistogramSum( 86 histogram_util.BROWSER_HISTOGRAM, 87 'Startup.BrowserMessageLoopStartTimeFromMainEntry', 88 tab) 89 process_creation_to_main = (process_creation_to_messageloop_start_ms - 90 main_to_messageloop_start_ms) 91 92 # User visible. 93 results.Add('process_creation_to_window_display', 'ms', 94 process_creation_to_window_display_ms) 95 results.Add('process_creation_to_foreground_tab_loaded', 'ms', 96 absolute_foreground_tab_loaded_ms - 97 absolute_browser_main_entry_ms + process_creation_to_main) 98 results.Add('process_creation_to_all_tabs_loaded', 'ms', 99 absolute_all_tabs_loaded_ms - 100 absolute_browser_main_entry_ms + process_creation_to_main) 101 102 # Critical code progression. 103 results.Add('process_creation_to_main', 'ms', 104 process_creation_to_main) 105 results.Add('main_to_messageloop_start', 'ms', 106 main_to_messageloop_start_ms) 107