blob: 5ea989796bd2b004bf75a62ca6007f4d016e5bf4 [file] [log] [blame]
# Copyright (c) 2012 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.
"""The page cycler measurement.
This measurement registers a window load handler in which is forces a layout and
then records the value of performance.now(). This call to now() measures the
time from navigationStart (immediately after the previous page's beforeunload
event) until after the layout in the page's load event. In addition, two garbage
collections are performed in between the page loads (in the beforeunload event).
This extra garbage collection time is not included in the measurement times.
Finally, various memory and IO statistics are gathered at the very end of
cycling all pages.
"""
import os
import sys
from metrics import histogram
from metrics import memory
from telemetry.core import util
from telemetry.page import page_measurement
MEMORY_HISTOGRAMS = [
{'name': 'V8.MemoryExternalFragmentationTotal', 'units': 'percent'},
{'name': 'V8.MemoryHeapSampleTotalCommitted', 'units': 'kb'},
{'name': 'V8.MemoryHeapSampleTotalUsed', 'units': 'kb'}]
class PageCycler(page_measurement.PageMeasurement):
def __init__(self, *args, **kwargs):
super(PageCycler, self).__init__(*args, **kwargs)
with open(os.path.join(os.path.dirname(__file__),
'page_cycler.js'), 'r') as f:
self._page_cycler_js = f.read()
self._memory_metric = None
self._histograms = None
def AddCommandLineOptions(self, parser):
# The page cyclers should default to 10 iterations. In order to change the
# default of an option, we must remove and re-add it.
# TODO: Remove this after transition to run_benchmark.
pageset_repeat_option = parser.get_option('--pageset-repeat')
pageset_repeat_option.default = 10
parser.remove_option('--pageset-repeat')
parser.add_option(pageset_repeat_option)
def DidStartBrowser(self, browser):
"""Initialize metrics once right after the browser has been launched."""
self._memory_metric = memory.MemoryMetric(browser)
self._memory_metric.Start()
self._histograms = [histogram.HistogramMetric(
h, histogram.RENDERER_HISTOGRAM)
for h in MEMORY_HISTOGRAMS]
def DidStartHTTPServer(self, tab):
# Avoid paying for a cross-renderer navigation on the first page on legacy
# page cyclers which use the filesystem.
tab.Navigate(tab.browser.http_server.UrlOf('nonexistent.html'))
def WillNavigateToPage(self, page, tab):
page.script_to_evaluate_on_commit = self._page_cycler_js
def DidNavigateToPage(self, page, tab):
for h in self._histograms:
h.Start(page, tab)
def CustomizeBrowserOptions(self, options):
options.AppendExtraBrowserArg('--enable-stats-collection-bindings')
options.AppendExtraBrowserArg('--js-flags=--expose_gc')
options.AppendExtraBrowserArg('--no-sandbox')
# Old commandline flags used for reference builds.
options.AppendExtraBrowserArg('--dom-automation')
# Temporarily disable typical_25 page set on mac.
if sys.platform == 'darwin' and sys.argv[-1].endswith('/typical_25.json'):
print 'typical_25 is currently disabled on mac. Skipping test.'
sys.exit(0)
def MeasureIO(self, tab, results):
io_stats = tab.browser.io_stats
if not io_stats['Browser']:
return
def AddSummariesForProcessType(process_type_io, process_type_trace):
if 'ReadOperationCount' in io_stats[process_type_io]:
results.AddSummary('read_operations_' + process_type_trace, '',
io_stats[process_type_io]
['ReadOperationCount'],
data_type='unimportant')
if 'WriteOperationCount' in io_stats[process_type_io]:
results.AddSummary('write_operations_' + process_type_trace, '',
io_stats[process_type_io]
['WriteOperationCount'],
data_type='unimportant')
if 'ReadTransferCount' in io_stats[process_type_io]:
results.AddSummary('read_bytes_' + process_type_trace, 'kb',
io_stats[process_type_io]
['ReadTransferCount'] / 1024,
data_type='unimportant')
if 'WriteTransferCount' in io_stats[process_type_io]:
results.AddSummary('write_bytes_' + process_type_trace, 'kb',
io_stats[process_type_io]
['WriteTransferCount'] / 1024,
data_type='unimportant')
AddSummariesForProcessType('Browser', 'browser')
AddSummariesForProcessType('Renderer', 'renderer')
AddSummariesForProcessType('Gpu', 'gpu')
def MeasurePage(self, page, tab, results):
def _IsDone():
return bool(tab.EvaluateJavaScript('__pc_load_time'))
util.WaitFor(_IsDone, 60)
for h in self._histograms:
h.GetValue(page, tab, results)
results.Add('page_load_time', 'ms',
int(float(tab.EvaluateJavaScript('__pc_load_time'))),
chart_name='times')
def DidRunTest(self, tab, results):
self._memory_metric.Stop()
self._memory_metric.AddResults(tab, results)
self.MeasureIO(tab, results)