Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py

Issue 2414363002: tools: Extend the CustomTabs benchmark scripts to speculative_prefetch. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # 2 #
3 # Copyright 2015 The Chromium Authors. All rights reserved. 3 # Copyright 2015 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """Loops Custom Tabs tests and outputs the results into a CSV file.""" 7 """Loops Custom Tabs tests and outputs the results into a CSV file."""
8 8
9 import contextlib 9 import contextlib
10 import logging 10 import logging
11 import optparse 11 import optparse
12 import os 12 import os
13 import random
13 import re 14 import re
14 import subprocess 15 import subprocess
15 import sys 16 import sys
16 import time 17 import time
17 18
18 _SRC_PATH = os.path.abspath(os.path.join( 19 _SRC_PATH = os.path.abspath(os.path.join(
19 os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, os.pardir)) 20 os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, os.pardir))
20 21
21 sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'catapult', 'devil')) 22 sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'catapult', 'devil'))
22 from devil.android import device_errors 23 from devil.android import device_errors
23 from devil.android import device_utils 24 from devil.android import device_utils
24 from devil.android.perf import cache_control 25 from devil.android.perf import cache_control
25 from devil.android.sdk import intent 26 from devil.android.sdk import intent
26 27
27 sys.path.append(os.path.join(_SRC_PATH, 'build', 'android')) 28 sys.path.append(os.path.join(_SRC_PATH, 'build', 'android'))
28 import devil_chromium 29 import devil_chromium
29 30
30 sys.path.append(os.path.join(_SRC_PATH, 'tools', 'android', 'loading')) 31 sys.path.append(os.path.join(_SRC_PATH, 'tools', 'android', 'loading'))
31 import device_setup 32 import device_setup
32 33
33 34
34 # Local build of Chrome (not Chromium). 35 # Local build of Chrome (not Chromium).
35 _CHROME_PACKAGE = 'com.google.android.apps.chrome' 36 _CHROME_PACKAGE = 'com.google.android.apps.chrome'
36 37 _COMMAND_LINE_PATH = '/data/local/tmp/chrome-command-line'
38 _TEST_APP_PACKAGE_NAME = 'org.chromium.customtabsclient.test'
37 39
38 # Command line arguments for Chrome. 40 # Command line arguments for Chrome.
39 _CHROME_ARGS = [ 41 _CHROME_ARGS = [
40 # Disable backgound network requests that may pollute WPR archive, pollute 42 # Disable backgound network requests that may pollute WPR archive, pollute
41 # HTTP cache generation, and introduce noise in loading performance. 43 # HTTP cache generation, and introduce noise in loading performance.
42 '--disable-background-networking', 44 '--disable-background-networking',
43 '--disable-default-apps', 45 '--disable-default-apps',
44 '--no-proxy-server', 46 '--no-proxy-server',
45 # TODO(droger): Remove once crbug.com/354743 is fixed. 47 # TODO(droger): Remove once crbug.com/354743 is fixed.
46 '--safebrowsing-disable-auto-update', 48 '--safebrowsing-disable-auto-update',
(...skipping 10 matching lines...) Expand all
57 def ResetChromeLocalState(device): 59 def ResetChromeLocalState(device):
58 """Remove the Chrome Profile and the various disk caches.""" 60 """Remove the Chrome Profile and the various disk caches."""
59 profile_dirs = ['app_chrome/Default', 'cache', 'app_chrome/ShaderCache', 61 profile_dirs = ['app_chrome/Default', 'cache', 'app_chrome/ShaderCache',
60 'app_tabs'] 62 'app_tabs']
61 cmd = ['rm', '-rf'] 63 cmd = ['rm', '-rf']
62 cmd.extend( 64 cmd.extend(
63 '/data/data/{}/{}'.format(_CHROME_PACKAGE, d) for d in profile_dirs) 65 '/data/data/{}/{}'.format(_CHROME_PACKAGE, d) for d in profile_dirs)
64 device.adb.Shell(subprocess.list2cmdline(cmd)) 66 device.adb.Shell(subprocess.list2cmdline(cmd))
65 67
66 68
67 def RunOnce(device, url, warmup, prerender_mode, delay_to_may_launch_url, 69 def RunOnce(device, url, warmup, speculation_mode, delay_to_may_launch_url,
68 delay_to_launch_url, cold): 70 delay_to_launch_url, cold, chrome_args):
69 """Runs a test on a device once. 71 """Runs a test on a device once.
70 72
71 Args: 73 Args:
72 device: (DeviceUtils) device to run the tests on. 74 device: (DeviceUtils) device to run the tests on.
75 url: (str) URL to load.
73 warmup: (bool) Whether to call warmup. 76 warmup: (bool) Whether to call warmup.
74 prerender_mode: (str) Prerender mode (disabled, enabled or prefetch). 77 speculation_mode: (str) Speculation Mode.
75 delay_to_may_launch_url: (int) Delay to mayLaunchUrl() in ms. 78 delay_to_may_launch_url: (int) Delay to mayLaunchUrl() in ms.
76 delay_to_launch_url: (int) Delay to launchUrl() in ms. 79 delay_to_launch_url: (int) Delay to launchUrl() in ms.
77 cold: (bool) Whether the page cache should be dropped. 80 cold: (bool) Whether the page cache should be dropped.
81 chrome_args: ([str]) List of arguments to pass to Chrome.
78 82
79 Returns: 83 Returns:
80 The output line (str), like this (one line only): 84 The output line (str), like this (one line only):
81 <warmup>,<prerender_mode>,<delay_to_may_launch_url>,<delay_to_launch>, 85 <warmup>,<prerender_mode>,<delay_to_may_launch_url>,<delay_to_launch>,
82 <intent_sent_ms>,<page_load_started_ms>,<page_load_finished_ms>, 86 <intent_sent_ms>,<page_load_started_ms>,<page_load_finished_ms>,
83 <first_contentful_paint> 87 <first_contentful_paint>
84 or None on error. 88 or None on error.
85 """ 89 """
86 launch_intent = intent.Intent( 90 with device_setup.FlagReplacer(device, _COMMAND_LINE_PATH, chrome_args):
87 action='android.intent.action.MAIN', 91 launch_intent = intent.Intent(
88 package='org.chromium.customtabsclient.test', 92 action='android.intent.action.MAIN',
89 activity='org.chromium.customtabs.test.MainActivity', 93 package=_TEST_APP_PACKAGE_NAME,
90 extras={'url': url, 'warmup': warmup, 'prerender_mode': prerender_mode, 94 activity='org.chromium.customtabs.test.MainActivity',
91 'delay_to_may_launch_url': delay_to_may_launch_url, 95 extras={'url': str(url), 'warmup': warmup,
92 'delay_to_launch_url': delay_to_launch_url}) 96 'speculation_mode': str(speculation_mode),
93 result_line_re = re.compile(r'CUSTOMTABSBENCH.*: (.*)') 97 'delay_to_may_launch_url': delay_to_may_launch_url,
94 logcat_monitor = device.GetLogcatMonitor(clear=True) 98 'delay_to_launch_url': delay_to_launch_url})
95 logcat_monitor.Start() 99 result_line_re = re.compile(r'CUSTOMTABSBENCH.*: (.*)')
96 device.ForceStop(_CHROME_PACKAGE) 100 logcat_monitor = device.GetLogcatMonitor(clear=True)
97 device.ForceStop('org.chromium.customtabsclient.test') 101 logcat_monitor.Start()
98 ResetChromeLocalState(device) 102 device.ForceStop(_CHROME_PACKAGE)
103 device.ForceStop(_TEST_APP_PACKAGE_NAME)
99 104
100 if cold:
101 if not device.HasRoot(): 105 if not device.HasRoot():
102 device.EnableRoot() 106 device.EnableRoot()
103 cache_control.CacheControl(device).DropRamCaches() 107 ResetChromeLocalState(device)
104 device.StartActivity(launch_intent, blocking=True) 108
105 match = None 109 if cold:
106 try: 110 cache_control.CacheControl(device).DropRamCaches()
107 match = logcat_monitor.WaitFor(result_line_re, timeout=20) 111
108 except device_errors.CommandTimeoutError as e: 112 device.StartActivity(launch_intent, blocking=True)
109 logging.warning('Timeout waiting for the result line') 113
110 return match.group(1) if match is not None else None 114 match = None
115 try:
116 match = logcat_monitor.WaitFor(result_line_re, timeout=20)
117 except device_errors.CommandTimeoutError as _:
118 logging.warning('Timeout waiting for the result line')
119 return match.group(1) if match is not None else None
111 120
112 121
113 def LoopOnDevice(device, url, warmup, prerender_mode, delay_to_may_launch_url, 122 def LoopOnDevice(device, configs, output_filename, wpr_archive_path=None,
114 delay_to_launch_url, cold, output_filename, once=False): 123 wpr_record=None, network_condition=None, wpr_log_path=None,
124 once=False, should_stop=None):
115 """Loops the tests on a device. 125 """Loops the tests on a device.
116 126
117 Args: 127 Args:
118 device: (DeviceUtils) device to run the tests on. 128 device: (DeviceUtils) device to run the tests on.
119 url: (str) URL to navigate to. 129 configs: ([dict])
120 warmup: (bool) Whether to call warmup.
121 prerender_mode: (str) Prerender mode (disabled, enabled or prefetch).
122 delay_to_may_launch_url: (int) Delay to mayLaunchUrl() in ms.
123 delay_to_launch_url: (int) Delay to launchUrl() in ms.
124 cold: (bool) Whether the page cache should be dropped.
125 output_filename: (str) Output filename. '-' for stdout. 130 output_filename: (str) Output filename. '-' for stdout.
131 wpr_archive_path: (str) Path to the WPR archive.
132 wpr_record: (bool) Whether WPR is set to recording.
133 network_condition: (str) Name of the network configuration for throttling.
134 wpr_log_path: (str) Path the the WPR log.
126 once: (bool) Run only once. 135 once: (bool) Run only once.
136 should_stop: (threading.Event or None) When the event is set, stop looping.
127 """ 137 """
128 while True: 138 with SetupWpr(device, wpr_archive_path, wpr_record, network_condition,
129 out = sys.stdout if output_filename == '-' else open(output_filename, 'a') 139 wpr_log_path) as wpr_attributes:
140 to_stdout = output_filename == '-'
141 out = sys.stdout if to_stdout else open(output_filename, 'a')
130 try: 142 try:
131 result = RunOnce(device, url, warmup, prerender_mode, 143 while should_stop is None or not should_stop.is_set():
132 delay_to_may_launch_url, delay_to_launch_url, cold) 144 config = configs[random.randint(0, len(configs) - 1)]
133 if result is not None: 145 chrome_args = _CHROME_ARGS + wpr_attributes.chrome_args
134 out.write(result + '\n') 146 if config['speculation_mode'] == 'no_state_prefetch':
135 out.flush() 147 chrome_args.append('--prerender=' + config['speculation_mode'])
136 if once: 148 result = RunOnce(device, config['url'], config['warmup'],
137 return 149 config['speculation_mode'],
138 time.sleep(10) 150 config['delay_to_may_launch_url'],
151 config['delay_to_launch_url'], config['cold'],
152 chrome_args)
153 if result is not None:
154 out.write(result + '\n')
155 out.flush()
156 if once:
157 return
158 if should_stop is not None:
159 should_stop.wait(10.)
160 else:
161 time.sleep(10)
139 finally: 162 finally:
140 if output_filename != '-': 163 if not to_stdout:
141 out.close() 164 out.close()
142 165
143 166
144 def ProcessOutput(filename): 167 def ProcessOutput(filename):
145 """Reads an output file, and returns a processed numpy array. 168 """Reads an output file, and returns a processed numpy array.
146 169
147 Args: 170 Args:
148 filename: (str) file to process. 171 filename: (str) file to process.
149 172
150 Returns: 173 Returns:
151 A numpy structured array. 174 A numpy structured array.
152 """ 175 """
153 import numpy as np 176 import numpy as np
154 data = np.genfromtxt(filename, delimiter=',') 177 data = np.genfromtxt(filename, delimiter=',')
155 result = np.array(np.zeros(len(data)), 178 result = np.array(np.zeros(len(data)),
156 dtype=[('warmup', bool), ('prerender_mode', np.int32), 179 dtype=[('warmup', bool), ('speculation_mode', np.int32),
157 ('delay_to_may_launch_url', np.int32), 180 ('delay_to_may_launch_url', np.int32),
158 ('delay_to_launch_url', np.int32), 181 ('delay_to_launch_url', np.int32),
159 ('commit', np.int32), ('plt', np.int32), 182 ('commit', np.int32), ('plt', np.int32),
160 ('first_contentful_paint', np.int32)]) 183 ('first_contentful_paint', np.int32)])
161 result['warmup'] = data[:, 0] 184 result['warmup'] = data[:, 0]
162 result['prerender_mode'] = data[:, 1] 185 result['speculation_mode'] = data[:, 1]
163 result['delay_to_may_launch_url'] = data[:, 2] 186 result['delay_to_may_launch_url'] = data[:, 2]
164 result['delay_to_launch_url'] = data[:, 3] 187 result['delay_to_launch_url'] = data[:, 3]
165 result['commit'] = data[:, 5] - data[:, 4] 188 result['commit'] = data[:, 5] - data[:, 4]
166 result['plt'] = data[:, 6] - data[:, 4] 189 result['plt'] = data[:, 6] - data[:, 4]
167 result['first_contentful_paint'] = data[7] 190 result['first_contentful_paint'] = data[7]
168 return result 191 return result
169 192
170 193
171 def _CreateOptionParser(): 194 def _CreateOptionParser():
172 parser = optparse.OptionParser(description='Loops Custom Tabs tests on a ' 195 parser = optparse.OptionParser(description='Loops Custom Tabs tests on a '
173 'device, and outputs the navigation timings ' 196 'device, and outputs the navigation timings '
174 'in a CSV file.') 197 'in a CSV file.')
175 parser.add_option('--device', help='Device ID') 198 parser.add_option('--device', help='Device ID')
176 parser.add_option('--url', help='URL to navigate to.', 199 parser.add_option('--url', help='URL to navigate to.',
177 default='https://www.android.com') 200 default='https://www.android.com')
178 parser.add_option('--warmup', help='Call warmup.', default=False, 201 parser.add_option('--warmup', help='Call warmup.', default=False,
179 action='store_true') 202 action='store_true')
180 parser.add_option('--prerender_mode', default='enabled', 203 parser.add_option('--speculation_mode', default='prerender',
181 help='The prerender mode (disabled, enabled or prefetch).', 204 help='The speculation mode (prerender, disabled, '
182 choices=['disabled', 'enabled', 'prefetch']) 205 'speculative_prefetch or no_state_prefetch).',
206 choices=['prerender', 'disabled', 'speculative_prefetch',
207 'no_state_prefetch'])
183 parser.add_option('--delay_to_may_launch_url', 208 parser.add_option('--delay_to_may_launch_url',
184 help='Delay before calling mayLaunchUrl() in ms.', 209 help='Delay before calling mayLaunchUrl() in ms.',
185 type='int') 210 type='int')
186 parser.add_option('--delay_to_launch_url', 211 parser.add_option('--delay_to_launch_url',
187 help='Delay before calling launchUrl() in ms.', 212 help='Delay before calling launchUrl() in ms.',
188 type='int') 213 type='int')
189 parser.add_option('--cold', help='Purge the page cache before each run.', 214 parser.add_option('--cold', help='Purge the page cache before each run.',
190 default=False, action='store_true') 215 default=False, action='store_true')
191 parser.add_option('--output_file', help='Output file (append). "-" for ' 216 parser.add_option('--output_file', help='Output file (append). "-" for '
192 'stdout') 217 'stdout')
193 parser.add_option('--once', help='Run only one iteration.', 218 parser.add_option('--once', help='Run only one iteration.',
194 action='store_true', default=False) 219 action='store_true', default=False)
195 220
196 # WebPageReplay-related options. 221 # WebPageReplay-related options.
197 group = optparse.OptionGroup( 222 group = optparse.OptionGroup(
198 parser, 'WebPageReplay options', 223 parser, 'WebPageReplay options',
199 'Setting any of these enables WebPageReplay.') 224 'Setting any of these enables WebPageReplay.')
200 group.add_option('--record', help='Record the WPR archive.', 225 group.add_option('--record', help='Record the WPR archive.',
201 action='store_true', default=False) 226 action='store_true', default=False)
202 group.add_option('--wpr_archive', help='WPR archive path.') 227 group.add_option('--wpr_archive', help='WPR archive path.')
203 group.add_option('--wpr_log', help='WPR log path.') 228 group.add_option('--wpr_log', help='WPR log path.')
204 group.add_option('--network_condition', 229 group.add_option('--network_condition',
205 help='Network condition for emulation.') 230 help='Network condition for emulation.')
206 parser.add_option_group(group) 231 parser.add_option_group(group)
207 232
208 return parser 233 return parser
209 234
210 235
211 @contextlib.contextmanager 236 @contextlib.contextmanager
212 def DummyWprHost(): 237 def DummyWprHost():
213 """Dummy context used to run without WebPageReplay.""" 238 """Dummy context used to run without WebPageReplay."""
214 yield device_setup.WprAttribute(chrome_args=[], chrome_env_override={}) 239 yield device_setup.WprAttribute(chrome_args=[], chrome_env_override={})
215 240
(...skipping 13 matching lines...) Expand all
229 parser = _CreateOptionParser() 254 parser = _CreateOptionParser()
230 options, _ = parser.parse_args() 255 options, _ = parser.parse_args()
231 devil_chromium.Initialize() 256 devil_chromium.Initialize()
232 devices = device_utils.DeviceUtils.HealthyDevices() 257 devices = device_utils.DeviceUtils.HealthyDevices()
233 device = devices[0] 258 device = devices[0]
234 if len(devices) != 1 and options.device is None: 259 if len(devices) != 1 and options.device is None:
235 logging.error('Several devices attached, must specify one with --device.') 260 logging.error('Several devices attached, must specify one with --device.')
236 sys.exit(0) 261 sys.exit(0)
237 if options.device is not None: 262 if options.device is not None:
238 matching_devices = [d for d in devices if str(d) == options.device] 263 matching_devices = [d for d in devices if str(d) == options.device]
239 if len(matching_devices) == 0: 264 if not matching_devices:
240 logging.error('Device not found.') 265 logging.error('Device not found.')
241 sys.exit(0) 266 sys.exit(0)
242 device = matching_devices[0] 267 device = matching_devices[0]
243 268
244 with SetupWpr(device, options.wpr_archive, options.record, 269 config = {
245 options.network_condition, options.wpr_log) as wpr_attributes: 270 'url': options.url,
246 chrome_args = (_CHROME_ARGS + ['--prerender=' + options.prerender_mode] + 271 'warmup': options.warmup,
247 wpr_attributes.chrome_args) 272 'speculation_mode': options.speculation_mode,
248 with device_setup.FlagReplacer( 273 'delay_to_may_launch_url': options.delay_to_may_launch_url,
249 device, '/data/local/tmp/chrome-command-line', chrome_args): 274 'delay_to_launch_url': options.delay_to_launch_url,
250 LoopOnDevice(device, options.url, options.warmup, options.prerender_mode, 275 'cold': options.cold,
251 options.delay_to_may_launch_url, options.delay_to_launch_url, 276 }
252 options.cold, options.output_file, options.once) 277 LoopOnDevice(device, [config], options.output_file, options.wpr_archive,
278 options.record, options.network_condition, options.wpr_log,
279 once=options.once)
253 280
254 281
255 if __name__ == '__main__': 282 if __name__ == '__main__':
256 main() 283 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698