OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # | 2 # |
3 # Copyright 2016 The Chromium Authors. All rights reserved. | 3 # Copyright 2016 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 """Loads a web page with speculative prefetch, and collects loading metrics.""" | 7 """Loads a web page with speculative prefetch, and collects loading metrics.""" |
8 | 8 |
9 import argparse | 9 import argparse |
10 import logging | 10 import logging |
11 import os | 11 import os |
| 12 import random |
12 import sys | 13 import sys |
13 import time | 14 import time |
14 | 15 |
15 _SRC_PATH = os.path.abspath(os.path.join( | 16 _SRC_PATH = os.path.abspath(os.path.join( |
16 os.path.dirname(__file__), os.pardir, os.pardir)) | 17 os.path.dirname(__file__), os.pardir, os.pardir)) |
17 | 18 |
18 sys.path.append(os.path.join( | 19 sys.path.append(os.path.join( |
19 _SRC_PATH, 'tools', 'android', 'customtabs_benchmark', 'scripts')) | 20 _SRC_PATH, 'tools', 'android', 'customtabs_benchmark', 'scripts')) |
20 import customtabs_benchmark | 21 import customtabs_benchmark |
21 import device_setup | 22 import device_setup |
22 | 23 |
23 sys.path.append(os.path.join(_SRC_PATH, 'tools', 'android', 'loading')) | 24 sys.path.append(os.path.join(_SRC_PATH, 'tools', 'android', 'loading')) |
| 25 import controller |
24 from options import OPTIONS | 26 from options import OPTIONS |
25 | 27 |
26 sys.path.append(os.path.join(_SRC_PATH, 'build', 'android')) | 28 sys.path.append(os.path.join(_SRC_PATH, 'build', 'android')) |
27 import devil_chromium | 29 import devil_chromium |
28 | 30 |
29 sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'catapult', 'devil')) | 31 sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'catapult', 'devil')) |
30 from devil.android.sdk import intent | 32 from devil.android.sdk import intent |
31 | 33 |
32 import prefetch_predictor_common | 34 import prefetch_predictor_common |
33 | 35 |
34 | 36 |
35 _EXTERNAL_PREFETCH_FLAG = ( | 37 _EXTERNAL_PREFETCH_FLAG = ( |
36 '--speculative-resource-prefetching=enabled-external-only') | 38 '--speculative-resource-prefetching=enabled-external-only') |
37 | 39 |
38 | 40 |
39 def _CreateArgumentParser(): | 41 def _CreateArgumentParser(): |
40 """Creates and returns the argument parser.""" | 42 """Creates and returns the argument parser.""" |
41 parser = argparse.ArgumentParser( | 43 parser = argparse.ArgumentParser( |
42 ('Loads a URL with the resource_prefetch_predictor and prints loading ' | 44 ('Loads a URL with the resource_prefetch_predictor and prints loading ' |
43 'metrics.'), parents=[OPTIONS.GetParentParser()]) | 45 'metrics.'), parents=[OPTIONS.GetParentParser()]) |
44 parser.add_argument('--device', help='Device ID') | 46 parser.add_argument('--device', help='Device ID') |
45 parser.add_argument('--database', | 47 parser.add_argument('--database', |
46 help=('File containing the predictor database, as ' | 48 help=('File containing the predictor database, as ' |
47 'obtained from generate_database.py.')) | 49 'obtained from generate_database.py.')) |
48 parser.add_argument('--url', help='URL to load.') | 50 parser.add_argument('--url', help='URL to load.') |
49 parser.add_argument('--prefetch_delay_ms', | 51 parser.add_argument('--prefetch_delays_ms', |
50 help='Prefetch delay in ms. -1 to disable prefetch.') | 52 help='List of prefetch delays in ms. -1 to disable ' |
| 53 'prefetch. Runs will randomly select one delay in the ' |
| 54 'list.') |
51 parser.add_argument('--output_filename', | 55 parser.add_argument('--output_filename', |
52 help='CSV file to append the result to.') | 56 help='CSV file to append the result to.') |
| 57 parser.add_argument('--network_condition', |
| 58 help='Network condition for emulation.') |
| 59 parser.add_argument('--wpr_archive', help='WPR archive path.') |
| 60 parser.add_argument('--once', help='Only run once.', action='store_true') |
53 return parser | 61 return parser |
54 | 62 |
55 | 63 |
56 def _Setup(device, database_filename): | 64 def _Setup(device, database_filename): |
57 """Sets up a device and returns an instance of RemoteChromeController.""" | 65 """Sets up a device and returns an instance of RemoteChromeController.""" |
58 chrome_controller = prefetch_predictor_common.Setup(device, ['']) | 66 chrome_controller = prefetch_predictor_common.Setup(device, ['']) |
59 chrome_package = OPTIONS.ChromePackage() | 67 chrome_package = OPTIONS.ChromePackage() |
60 device.ForceStop(chrome_package.package) | 68 device.ForceStop(chrome_package.package) |
61 chrome_controller.ResetBrowserState() | 69 chrome_controller.ResetBrowserState() |
62 device_database_filename = prefetch_predictor_common.DatabaseDevicePath() | 70 device_database_filename = prefetch_predictor_common.DatabaseDevicePath() |
(...skipping 18 matching lines...) Expand all Loading... |
81 group = stats['st_group'] | 89 group = stats['st_group'] |
82 # Now push the database. Needs to be done after the first launch, otherwise | 90 # Now push the database. Needs to be done after the first launch, otherwise |
83 # the profile directory is owned by root. Also change the owner of the | 91 # the profile directory is owned by root. Also change the owner of the |
84 # database, since adb push sets it to root. | 92 # database, since adb push sets it to root. |
85 database_content = open(database_filename, 'r').read() | 93 database_content = open(database_filename, 'r').read() |
86 device.WriteFile(device_database_filename, database_content, force_push=True) | 94 device.WriteFile(device_database_filename, database_content, force_push=True) |
87 command = 'chown %s:%s \'%s\'' % (owner, group, device_database_filename) | 95 command = 'chown %s:%s \'%s\'' % (owner, group, device_database_filename) |
88 device.RunShellCommand(command, as_root=True) | 96 device.RunShellCommand(command, as_root=True) |
89 | 97 |
90 | 98 |
91 def _Go(device, url, prefetch_delay_ms): | 99 def _RunOnce(device, database_filename, url, prefetch_delay_ms, |
| 100 output_filename, wpr_archive, network_condition): |
| 101 _Setup(device, database_filename) |
| 102 |
92 disable_prefetch = prefetch_delay_ms == -1 | 103 disable_prefetch = prefetch_delay_ms == -1 |
93 # Startup tracing to ease debugging. | 104 # Startup tracing to ease debugging. |
94 chrome_args = (customtabs_benchmark.CHROME_ARGS | 105 chrome_args = (customtabs_benchmark.CHROME_ARGS |
95 + ['--trace-startup', '--trace-startup-duration=20']) | 106 + ['--trace-startup', '--trace-startup-duration=20']) |
96 if not disable_prefetch: | 107 if not disable_prefetch: |
97 chrome_args.append(_EXTERNAL_PREFETCH_FLAG) | 108 chrome_args.append(_EXTERNAL_PREFETCH_FLAG) |
98 prefetch_mode = 'disabled' if disable_prefetch else 'speculative_prefetch' | 109 |
99 result = customtabs_benchmark.RunOnce( | 110 chrome_controller = controller.RemoteChromeController(device) |
100 device, url, warmup=True, speculation_mode=prefetch_mode, | 111 device.ForceStop(OPTIONS.ChromePackage().package) |
101 delay_to_may_launch_url=2000, | 112 chrome_controller.AddChromeArguments(chrome_args) |
102 delay_to_launch_url=prefetch_delay_ms, cold=False, | 113 |
103 chrome_args=chrome_args, reset_chrome_state=False) | 114 with device_setup.RemoteWprHost( |
104 return customtabs_benchmark.ParseResult(result) | 115 device, wpr_archive, record=False, |
| 116 network_condition_name=network_condition) as wpr: |
| 117 logging.info('WPR arguments: ' + ' '.join(wpr.chrome_args)) |
| 118 chrome_args += wpr.chrome_args |
| 119 prefetch_mode = 'disabled' if disable_prefetch else 'speculative_prefetch' |
| 120 result = customtabs_benchmark.RunOnce( |
| 121 device, url, warmup=True, speculation_mode=prefetch_mode, |
| 122 delay_to_may_launch_url=2000, |
| 123 delay_to_launch_url=prefetch_delay_ms, cold=False, |
| 124 chrome_args=chrome_args, reset_chrome_state=False) |
| 125 data_point = customtabs_benchmark.ParseResult(result) |
| 126 |
| 127 with open(output_filename, 'a') as f: |
| 128 f.write(','.join(str(x) for x in data_point) + '\n') |
105 | 129 |
106 | 130 |
107 def main(): | 131 def main(): |
108 logging.basicConfig(level=logging.INFO) | 132 logging.basicConfig(level=logging.INFO) |
109 devil_chromium.Initialize() | 133 devil_chromium.Initialize() |
110 | 134 |
111 parser = _CreateArgumentParser() | 135 parser = _CreateArgumentParser() |
112 args = parser.parse_args() | 136 args = parser.parse_args() |
113 OPTIONS.SetParsedArgs(args) | 137 OPTIONS.SetParsedArgs(args) |
| 138 |
| 139 if os.path.exists(args.output_filename): |
| 140 logging.error('Output file %s already exists.' % args.output_filename) |
| 141 sys.exit(1) |
| 142 |
114 device = prefetch_predictor_common.FindDevice(args.device) | 143 device = prefetch_predictor_common.FindDevice(args.device) |
115 if device is None: | 144 if device is None: |
116 logging.error('Could not find device: %s.', args.device) | 145 logging.error('Could not find device: %s.', args.device) |
117 sys.exit(1) | 146 sys.exit(1) |
118 | 147 |
119 _Setup(device, args.database) | 148 delays = [int(x) for x in args.prefetch_delays_ms.split(',')] |
120 result = _Go(device, args.url, int(args.prefetch_delay_ms)) | 149 |
121 print result | 150 with open(args.output_filename, 'w') as f: |
122 with open(args.output_filename, 'a') as f: | 151 f.write(','.join(customtabs_benchmark.RESULT_FIELDS) + '\n') |
123 f.write(','.join(str(x) for x in result) + '\n') | 152 |
| 153 while True: |
| 154 delay = delays[random.randint(0, len(delays) - 1)] |
| 155 _RunOnce(device, args.database, args.url, delay, args.output_filename, |
| 156 args.wpr_archive, args.network_condition) |
| 157 if args.once: |
| 158 return |
124 | 159 |
125 | 160 |
126 if __name__ == '__main__': | 161 if __name__ == '__main__': |
127 main() | 162 main() |
OLD | NEW |