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