OLD | NEW |
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 logging | 9 import logging |
10 import optparse | 10 import optparse |
11 import os | 11 import os |
12 import re | 12 import re |
13 import subprocess | 13 import subprocess |
14 import sys | 14 import sys |
15 import time | 15 import time |
16 | 16 |
17 _SRC_PATH = os.path.abspath(os.path.join( | 17 _SRC_PATH = os.path.abspath(os.path.join( |
18 os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, os.pardir)) | 18 os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, os.pardir)) |
19 | 19 |
20 sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'catapult', 'devil')) | 20 sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'catapult', 'devil')) |
21 from devil.android import device_errors | 21 from devil.android import device_errors |
22 from devil.android import device_utils | 22 from devil.android import device_utils |
23 from devil.android.perf import cache_control | 23 from devil.android.perf import cache_control |
24 from devil.android.sdk import intent | 24 from devil.android.sdk import intent |
25 | 25 |
26 sys.path.append(os.path.join(_SRC_PATH, 'build', 'android')) | 26 sys.path.append(os.path.join(_SRC_PATH, 'build', 'android')) |
27 import devil_chromium | 27 import devil_chromium |
28 | 28 |
| 29 sys.path.append(os.path.join(_SRC_PATH, 'tools', 'android', 'loading')) |
| 30 import device_setup |
| 31 |
29 | 32 |
30 # Local build of Chrome (not Chromium). | 33 # Local build of Chrome (not Chromium). |
31 _CHROME_PACKAGE = 'com.google.android.apps.chrome' | 34 _CHROME_PACKAGE = 'com.google.android.apps.chrome' |
32 | 35 |
33 | 36 |
| 37 # Command line arguments for Chrome. |
| 38 _CHROME_ARGS = [ |
| 39 # Disable backgound network requests that may pollute WPR archive, pollute |
| 40 # HTTP cache generation, and introduce noise in loading performance. |
| 41 '--disable-background-networking', |
| 42 '--disable-default-apps', |
| 43 '--no-proxy-server', |
| 44 # TODO(droger): Remove once crbug.com/354743 is fixed. |
| 45 '--safebrowsing-disable-auto-update', |
| 46 |
| 47 # Disables actions that chrome performs only on first run or each launches, |
| 48 # which can interfere with page load performance, or even block its |
| 49 # execution by waiting for user input. |
| 50 '--disable-fre', |
| 51 '--no-default-browser-check', |
| 52 '--no-first-run', |
| 53 ] |
| 54 |
| 55 |
34 def ResetChromeLocalState(device): | 56 def ResetChromeLocalState(device): |
35 """Remove the Chrome Profile and the various disk caches.""" | 57 """Remove the Chrome Profile and the various disk caches.""" |
36 profile_dirs = ['app_chrome/Default', 'cache', 'app_chrome/ShaderCache', | 58 profile_dirs = ['app_chrome/Default', 'cache', 'app_chrome/ShaderCache', |
37 'app_tabs'] | 59 'app_tabs'] |
38 cmd = ['rm', '-rf'] | 60 cmd = ['rm', '-rf'] |
39 cmd.extend( | 61 cmd.extend( |
40 '/data/data/{}/{}'.format(_CHROME_PACKAGE, d) for d in profile_dirs) | 62 '/data/data/{}/{}'.format(_CHROME_PACKAGE, d) for d in profile_dirs) |
41 device.adb.Shell(subprocess.list2cmdline(cmd)) | 63 device.adb.Shell(subprocess.list2cmdline(cmd)) |
42 | 64 |
43 | 65 |
44 def RunOnce(device, url, warmup, no_prerendering, delay_to_may_launch_url, | 66 def RunOnce(device, url, warmup, prerender_mode, delay_to_may_launch_url, |
45 delay_to_launch_url, cold): | 67 delay_to_launch_url, cold): |
46 """Runs a test on a device once. | 68 """Runs a test on a device once. |
47 | 69 |
48 Args: | 70 Args: |
49 device: (DeviceUtils) device to run the tests on. | 71 device: (DeviceUtils) device to run the tests on. |
50 warmup: (bool) Whether to call warmup. | 72 warmup: (bool) Whether to call warmup. |
51 no_prerendering: (bool) Whether to disable prerendering. | 73 prerender_mode: (str) Prerender mode (disabled, enabled or prefetch). |
52 delay_to_may_launch_url: (int) Delay to mayLaunchUrl() in ms. | 74 delay_to_may_launch_url: (int) Delay to mayLaunchUrl() in ms. |
53 delay_to_launch_url: (int) Delay to launchUrl() in ms. | 75 delay_to_launch_url: (int) Delay to launchUrl() in ms. |
54 cold: (bool) Whether the page cache should be dropped. | 76 cold: (bool) Whether the page cache should be dropped. |
55 | 77 |
56 Returns: | 78 Returns: |
57 The output line (str), like this (one line only): | 79 The output line (str), like this (one line only): |
58 <warmup>,<no_prerendering>,<delay_to_may_launch_url>,<delay_to_launch>, | 80 <warmup>,<prerender_mode>,<delay_to_may_launch_url>,<delay_to_launch>, |
59 <intent_sent_ms>,<page_load_started_ms>,<page_load_finished_ms> | 81 <intent_sent_ms>,<page_load_started_ms>,<page_load_finished_ms> |
60 or None on error. | 82 or None on error. |
61 """ | 83 """ |
62 launch_intent = intent.Intent( | 84 launch_intent = intent.Intent( |
63 action='android.intent.action.MAIN', | 85 action='android.intent.action.MAIN', |
64 package='org.chromium.customtabsclient.test', | 86 package='org.chromium.customtabsclient.test', |
65 activity='org.chromium.customtabs.test.MainActivity', | 87 activity='org.chromium.customtabs.test.MainActivity', |
66 extras={'url': url, 'warmup': warmup, 'no_prerendering': no_prerendering, | 88 extras={'url': url, 'warmup': warmup, 'prerender_mode': prerender_mode, |
67 'delay_to_may_launch_url': delay_to_may_launch_url, | 89 'delay_to_may_launch_url': delay_to_may_launch_url, |
68 'delay_to_launch_url': delay_to_launch_url}) | 90 'delay_to_launch_url': delay_to_launch_url}) |
69 result_line_re = re.compile(r'CUSTOMTABSBENCH.*: (.*)') | 91 result_line_re = re.compile(r'CUSTOMTABSBENCH.*: (.*)') |
70 logcat_monitor = device.GetLogcatMonitor(clear=True) | 92 logcat_monitor = device.GetLogcatMonitor(clear=True) |
71 logcat_monitor.Start() | 93 logcat_monitor.Start() |
72 device.ForceStop(_CHROME_PACKAGE) | 94 device.ForceStop(_CHROME_PACKAGE) |
73 device.ForceStop('org.chromium.customtabsclient.test') | 95 device.ForceStop('org.chromium.customtabsclient.test') |
74 ResetChromeLocalState(device) | 96 ResetChromeLocalState(device) |
75 | 97 |
76 if cold: | 98 if cold: |
77 if not device.HasRoot(): | 99 if not device.HasRoot(): |
78 device.EnableRoot() | 100 device.EnableRoot() |
79 cache_control.CacheControl(device).DropRamCaches() | 101 cache_control.CacheControl(device).DropRamCaches() |
80 device.StartActivity(launch_intent, blocking=True) | 102 device.StartActivity(launch_intent, blocking=True) |
81 match = None | 103 match = None |
82 try: | 104 try: |
83 match = logcat_monitor.WaitFor(result_line_re, timeout=10) | 105 match = logcat_monitor.WaitFor(result_line_re, timeout=10) |
84 except device_errors.CommandTimeoutError as e: | 106 except device_errors.CommandTimeoutError as e: |
85 logging.warning('Timeout waiting for the result line') | 107 logging.warning('Timeout waiting for the result line') |
86 return match.group(1) if match is not None else None | 108 return match.group(1) if match is not None else None |
87 | 109 |
88 | 110 |
89 def LoopOnDevice(device, url, warmup, no_prerendering, delay_to_may_launch_url, | 111 def LoopOnDevice(device, url, warmup, prerender_mode, delay_to_may_launch_url, |
90 delay_to_launch_url, cold, output_filename, once=False): | 112 delay_to_launch_url, cold, output_filename, once=False): |
91 """Loops the tests on a device. | 113 """Loops the tests on a device. |
92 | 114 |
93 Args: | 115 Args: |
94 device: (DeviceUtils) device to run the tests on. | 116 device: (DeviceUtils) device to run the tests on. |
95 url: (str) URL to navigate to. | 117 url: (str) URL to navigate to. |
96 warmup: (bool) Whether to call warmup. | 118 warmup: (bool) Whether to call warmup. |
97 no_prerendering: (bool) Whether to disable prerendering. | 119 prerender_mode: (str) Prerender mode (disabled, enabled or prefetch). |
98 delay_to_may_launch_url: (int) Delay to mayLaunchUrl() in ms. | 120 delay_to_may_launch_url: (int) Delay to mayLaunchUrl() in ms. |
99 delay_to_launch_url: (int) Delay to launchUrl() in ms. | 121 delay_to_launch_url: (int) Delay to launchUrl() in ms. |
100 cold: (bool) Whether the page cache should be dropped. | 122 cold: (bool) Whether the page cache should be dropped. |
101 output_filename: (str) Output filename. '-' for stdout. | 123 output_filename: (str) Output filename. '-' for stdout. |
102 once: (bool) Run only once. | 124 once: (bool) Run only once. |
103 """ | 125 """ |
104 while True: | 126 while True: |
105 out = sys.stdout if output_filename == '-' else open(output_filename, 'a') | 127 out = sys.stdout if output_filename == '-' else open(output_filename, 'a') |
106 try: | 128 try: |
107 result = RunOnce(device, url, warmup, no_prerendering, | 129 result = RunOnce(device, url, warmup, prerender_mode, |
108 delay_to_may_launch_url, delay_to_launch_url, cold) | 130 delay_to_may_launch_url, delay_to_launch_url, cold) |
109 if result is not None: | 131 if result is not None: |
110 out.write(result + '\n') | 132 out.write(result + '\n') |
111 out.flush() | 133 out.flush() |
112 if once: | 134 if once: |
113 return | 135 return |
114 time.sleep(10) | 136 time.sleep(10) |
115 finally: | 137 finally: |
116 if output_filename != '-': | 138 if output_filename != '-': |
117 out.close() | 139 out.close() |
118 | 140 |
119 | 141 |
120 def ProcessOutput(filename): | 142 def ProcessOutput(filename): |
121 """Reads an output file, and returns a processed numpy array. | 143 """Reads an output file, and returns a processed numpy array. |
122 | 144 |
123 Args: | 145 Args: |
124 filename: (str) file to process. | 146 filename: (str) file to process. |
125 | 147 |
126 Returns: | 148 Returns: |
127 A numpy structured array. | 149 A numpy structured array. |
128 """ | 150 """ |
129 import numpy as np | 151 import numpy as np |
130 data = np.genfromtxt(filename, delimiter=',') | 152 data = np.genfromtxt(filename, delimiter=',') |
131 result = np.array(np.zeros(len(data)), | 153 result = np.array(np.zeros(len(data)), |
132 dtype=[('warmup', bool), ('no_prerendering', bool), | 154 dtype=[('warmup', bool), ('prerender_mode', np.int32), |
133 ('delay_to_may_launch_url', np.int32), | 155 ('delay_to_may_launch_url', np.int32), |
134 ('delay_to_launch_url', np.int32), | 156 ('delay_to_launch_url', np.int32), |
135 ('commit', np.int32), ('plt', np.int32)]) | 157 ('commit', np.int32), ('plt', np.int32)]) |
136 result['warmup'] = data[:, 0] | 158 result['warmup'] = data[:, 0] |
137 result['no_prerendering'] = data[:, 1] | 159 result['prerender_mode'] = data[:, 1] |
138 result['delay_to_may_launch_url'] = data[:, 2] | 160 result['delay_to_may_launch_url'] = data[:, 2] |
139 result['delay_to_launch_url'] = data[:, 3] | 161 result['delay_to_launch_url'] = data[:, 3] |
140 result['commit'] = data[:, 5] - data[:, 4] | 162 result['commit'] = data[:, 5] - data[:, 4] |
141 result['plt'] = data[:, 6] - data[:, 4] | 163 result['plt'] = data[:, 6] - data[:, 4] |
142 return result | 164 return result |
143 | 165 |
144 | 166 |
145 def _CreateOptionParser(): | 167 def _CreateOptionParser(): |
146 parser = optparse.OptionParser(description='Loops Custom Tabs tests on a ' | 168 parser = optparse.OptionParser(description='Loops Custom Tabs tests on a ' |
147 'device, and outputs the navigation timings ' | 169 'device, and outputs the navigation timings ' |
148 'in a CSV file.') | 170 'in a CSV file.') |
149 parser.add_option('--device', help='Device ID') | 171 parser.add_option('--device', help='Device ID') |
150 parser.add_option('--url', help='URL to navigate to.', | 172 parser.add_option('--url', help='URL to navigate to.', |
151 default='https://www.android.com') | 173 default='https://www.android.com') |
152 parser.add_option('--warmup', help='Call warmup.', default=False, | 174 parser.add_option('--warmup', help='Call warmup.', default=False, |
153 action='store_true') | 175 action='store_true') |
154 parser.add_option('--no_prerendering', help='Disable prerendering.', | 176 parser.add_option('--prerender_mode', default='enabled', |
155 default=False, action='store_true') | 177 help='The prerender mode (disabled, enabled or prefetch).', |
| 178 choices=['disabled', 'enabled', 'prefetch']) |
156 parser.add_option('--delay_to_may_launch_url', | 179 parser.add_option('--delay_to_may_launch_url', |
157 help='Delay before calling mayLaunchUrl() in ms.', | 180 help='Delay before calling mayLaunchUrl() in ms.', |
158 type='int') | 181 type='int') |
159 parser.add_option('--delay_to_launch_url', | 182 parser.add_option('--delay_to_launch_url', |
160 help='Delay before calling launchUrl() in ms.', | 183 help='Delay before calling launchUrl() in ms.', |
161 type='int') | 184 type='int') |
162 parser.add_option('--cold', help='Purge the page cache before each run.', | 185 parser.add_option('--cold', help='Purge the page cache before each run.', |
163 default=False, action='store_true') | 186 default=False, action='store_true') |
164 parser.add_option('--output_file', help='Output file (append). "-" for ' | 187 parser.add_option('--output_file', help='Output file (append). "-" for ' |
165 'stdout') | 188 'stdout') |
(...skipping 10 matching lines...) Expand all Loading... |
176 device = devices[0] | 199 device = devices[0] |
177 if len(devices) != 1 and options.device is None: | 200 if len(devices) != 1 and options.device is None: |
178 logging.error('Several devices attached, must specify one with --device.') | 201 logging.error('Several devices attached, must specify one with --device.') |
179 sys.exit(0) | 202 sys.exit(0) |
180 if options.device is not None: | 203 if options.device is not None: |
181 matching_devices = [d for d in devices if str(d) == options.device] | 204 matching_devices = [d for d in devices if str(d) == options.device] |
182 if len(matching_devices) == 0: | 205 if len(matching_devices) == 0: |
183 logging.error('Device not found.') | 206 logging.error('Device not found.') |
184 sys.exit(0) | 207 sys.exit(0) |
185 device = matching_devices[0] | 208 device = matching_devices[0] |
186 LoopOnDevice(device, options.url, options.warmup, options.no_prerendering, | 209 |
187 options.delay_to_may_launch_url, options.delay_to_launch_url, | 210 with device_setup.FlagReplacer( |
188 options.cold, options.output_file, options.once) | 211 device, '/data/local/tmp/chrome-command-line', |
| 212 _CHROME_ARGS + ['--prerender=' + options.prerender_mode]): |
| 213 LoopOnDevice(device, options.url, options.warmup, |
| 214 options.prerender_mode, |
| 215 options.delay_to_may_launch_url, options.delay_to_launch_url, |
| 216 options.cold, options.output_file, options.once) |
189 | 217 |
190 | 218 |
191 if __name__ == '__main__': | 219 if __name__ == '__main__': |
192 main() | 220 main() |
OLD | NEW |