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

Side by Side Diff: tools/android/customtabs_benchmark/scripts/run_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/env python 1 #!/usr/bin/env 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 copy 9 import copy
10 import json 10 import json
11 import logging 11 import logging
12 import optparse 12 import optparse
13 import os 13 import os
14 import random
15 import sys 14 import sys
16 import threading 15 import threading
17 16
18 import customtabs_benchmark 17 import customtabs_benchmark
19 18
20 _SRC_PATH = os.path.abspath(os.path.join( 19 _SRC_PATH = os.path.abspath(os.path.join(
21 os.path.dirname(__file__), '..', '..', '..', '..')) 20 os.path.dirname(__file__), '..', '..', '..', '..'))
22 21
23 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'))
24 from devil.android import device_utils 23 from devil.android import device_utils
25 24
26 sys.path.append(os.path.join(_SRC_PATH, 'build', 'android')) 25 sys.path.append(os.path.join(_SRC_PATH, 'build', 'android'))
27 import devil_chromium 26 import devil_chromium
28 27
29 28
30 _KEYS = ['url', 'warmup', 'no_prerendering', 'delay_to_may_launch_url', 29 _KEYS = ['url', 'warmup', 'speculation_mode', 'delay_to_may_launch_url',
31 'delay_to_launch_url', 'cold'] 30 'delay_to_launch_url', 'cold']
32 31
33 32
34 def _ParseConfiguration(filename): 33 def _ParseConfiguration(filename):
35 """Reads a JSON file and returns a list of configurations. 34 """Reads a JSON file and returns a list of configurations.
36 35
37 Each valid value in the JSON file can be either a scalar or a list of 36 Each valid value in the JSON file can be either a scalar or a list of
38 values. This function expands the scalar values to be lists. All list must 37 values. This function expands the scalar values to be lists. All list must
39 have the same length. 38 have the same length.
40 39
41 Sample configuration: 40 Sample configuration:
42 { 41 {
43 "url": "https://www.android.com", 42 "url": "https://www.android.com",
44 "warmup": [false, true], 43 "warmup": [false, true],
45 "no_prerendering": false, 44 "speculation_mode": "speculative_prefetch",
46 "delay_to_may_launch_url": [-1, 1000], 45 "delay_to_may_launch_url": [-1, 1000],
47 "delay_to_launch_url": [-1, 1000], 46 "delay_to_launch_url": [-1, 1000],
48 "cold": true 47 "cold": true
49 } 48 }
49 See sample_config.json in this directory as well.
50 50
51 Args: 51 Args:
52 filename: (str) Point to a file containins a JSON dictionnary of config 52 filename: (str) Point to a file containins a JSON dictionnary of config
53 values. 53 values.
54 54
55 Returns: 55 Returns:
56 A list of configurations, where each value is specified. 56 A list of configurations, where each value is specified.
57 """ 57 """
58 config = json.load(open(filename, 'r')) 58 config = json.load(open(filename, 'r'))
59 has_all_values = all(k in config for k in _KEYS) 59 has_all_values = all(k in config for k in _KEYS)
60 assert has_all_values 60 assert has_all_values
61 config['url'] = str(config['url']) # Intents don't like unicode. 61 config['url'] = str(config['url']) # Intents don't like unicode.
62 has_list = any(isinstance(config[k], list) for k in _KEYS) 62 has_list = any(isinstance(config[k], list) for k in _KEYS)
63 if not has_list: 63 if not has_list:
64 return [config] 64 return [config]
65 list_keys = [k for k in _KEYS if isinstance(config[k], list)] 65 list_keys = [k for k in _KEYS if isinstance(config[k], list)]
66 list_length = len(config[list_keys[0]]) 66 list_length = len(config[list_keys[0]])
67 assert all(len(config[k]) == list_length for k in list_keys) 67 assert all(len(config[k]) == list_length for k in list_keys)
68 result = [] 68 result = []
69 for i in range(list_length): 69 for i in range(list_length):
70 result.append(copy.deepcopy(config)) 70 result.append(copy.deepcopy(config))
71 for k in list_keys: 71 for k in list_keys:
72 result[-1][k] = result[-1][k][i] 72 result[-1][k] = result[-1][k][i]
73 return result 73 return result
74 74
75 75
76 def _CreateOptionParser(): 76 def _CreateOptionParser():
77 parser = optparse.OptionParser(description='Loops tests on all attached ' 77 parser = optparse.OptionParser(description='Loops tests on all attached '
78 'devices, with randomly selected ' 78 'devices, with randomly selected '
79 'configurations, and outputs the results in ' 79 'configurations, and outputs the results in '
80 'CSV files.') 80 'CSV files.')
81 parser.add_option('--config', help='JSON configuration file. Required.') 81 parser.add_option('--config', help='JSON configuration file. Required.')
82 parser.add_option('--output_file_prefix', help='Output file prefix. Actual ' 82 parser.add_option('--output_file_prefix', help='Output file prefix. Actual '
83 'output file is prefix_<device ID>.csv', default='result') 83 'output file is prefix_<device ID>.csv', default='result')
84 parser.add_option('--once', help='Run only once.', default=False,
85 action='store_true')
84 return parser 86 return parser
85 87
86 88
87 def _RunOnDevice(device, output_filename, configs, should_stop):
88 """Loops the tests described by configs on a device.
89
90 Args:
91 device: (DeviceUtils) device to run the tests on.
92 output_filename: (str) Output file name.
93 configs: (list of dict) List of configurations.
94 should_stop: (Event) When set, this function should return.
95 """
96 with open(output_filename, 'a') as f:
97 while not should_stop.is_set():
98 config = configs[random.randint(0, len(configs) - 1)]
99 result = customtabs_benchmark.RunOnce(
100 device, config['url'], config['warmup'], config['no_prerendering'],
101 config['delay_to_may_launch_url'], config['delay_to_launch_url'],
102 config['cold'])
103 if result is not None:
104 f.write(result + '\n')
105 f.flush()
106 should_stop.wait(10.)
107
108
109 def _Run(output_file_prefix, configs): 89 def _Run(output_file_prefix, configs):
110 """Loops the tests described by the configs on connected devices. 90 """Loops the tests described by the configs on connected devices.
111 91
112 Args: 92 Args:
113 output_file_prefix: (str) Prefix for the output file name. 93 output_file_prefix: (str) Prefix for the output file name.
114 configs: (list of dict) List of configurations. 94 configs: ([dict]) List of configurations.
115 """ 95 """
116 devices = device_utils.DeviceUtils.HealthyDevices() 96 devices = device_utils.DeviceUtils.HealthyDevices()
117 should_stop = threading.Event() 97 stop_event = threading.Event()
118 threads = [] 98 threads = []
119 for device in devices: 99 for device in devices:
120 output_filename = '%s_%s.csv' % (output_file_prefix, str(device)) 100 output_filename = '%s_%s.csv' % (output_file_prefix, str(device))
121 thread = threading.Thread( 101 thread = threading.Thread(
122 target=_RunOnDevice, 102 target=customtabs_benchmark.LoopOnDevice,
123 args=(device, output_filename, configs, should_stop)) 103 args=(device, configs, output_filename),
104 kwargs={'should_stop': stop_event})
124 thread.start() 105 thread.start()
125 threads.append(thread) 106 threads.append(thread)
126 for thread in threads: 107 while any(thread.is_alive() for thread in threads):
127 try: 108 try:
128 thread.join() 109 for thread in threads:
129 except KeyboardInterrupt as e: 110 if thread.is_alive():
130 should_stop.set() 111 thread.join(1.)
112 except KeyboardInterrupt as _:
113 logging.warning('Stopping now.')
114 stop_event.set()
131 115
132 116
133 def main(): 117 def main():
134 parser = _CreateOptionParser() 118 parser = _CreateOptionParser()
135 options, _ = parser.parse_args() 119 options, _ = parser.parse_args()
136 if options.config is None: 120 if options.config is None:
137 logging.error('A configuration file must be provided.') 121 logging.error('A configuration file must be provided.')
138 sys.exit(0) 122 sys.exit(0)
139 devil_chromium.Initialize() 123 devil_chromium.Initialize()
140 configs = _ParseConfiguration(options.config) 124 configs = _ParseConfiguration(options.config)
141 _Run(options.output_file_prefix, configs) 125 if options.once:
126 device = device_utils.DeviceUtils.HealthyDevices()[0]
127 customtabs_benchmark.LoopOnDevice(device, [configs[0]], '-', once=True)
128 else:
129 _Run(options.output_file_prefix, configs)
142 130
143 131
144 if __name__ == '__main__': 132 if __name__ == '__main__':
145 main() 133 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698