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.
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(
37 'Startup.BrowserMainEntryTimeAbsoluteHighWord',
39 low_bytes
= histogram_util
.GetHistogramSum(
41 'Startup.BrowserMainEntryTimeAbsoluteLowWord',
43 if high_bytes
== 0 and low_bytes
== 0:
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. """
50 TabLoadTime
= collections
.namedtuple(
52 ['load_start_ms', 'load_duration_ms', 'request_start_ms'])
54 def RecordTabLoadTime(t
):
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."
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
)
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
:
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."
128 self
._RecordTabLoadTimes
(tab
, browser_main_entry_time_ms
, results
)