OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright 2016 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """Script to generate chromium.perf.json and chromium.perf.fyi.json in | |
7 the src/testing/buildbot directory. Maintaining these files by hand is | |
8 too unwieldy. | |
9 """ | |
10 import argparse | |
11 import json | |
12 import os | |
13 import sys | |
14 | |
15 from chrome_telemetry_build import chromium_config | |
16 | |
17 sys.path.append(chromium_config.GetTelemetryDir()) | |
18 from telemetry import benchmark as benchmark_module | |
19 from telemetry.core import discover | |
20 from telemetry.util import bot_utils | |
21 | |
22 | |
23 SCRIPT_TESTS = [ | |
24 { | |
25 'args': [ | |
26 'gpu_perftests', | |
27 '--adb-path', | |
28 'src/third_party/catapult/devil/bin/deps/linux2/x86_64/bin/adb', | |
29 ], | |
30 'name': 'gpu_perftests', | |
31 'script': 'gtest_perf_test.py', | |
32 'testers': { | |
33 'chromium.perf': [ | |
34 { | |
35 'name': 'Android Nexus5 Perf', | |
36 'shards': [2] | |
37 }, | |
38 { | |
39 'name': 'Android Nexus7v2 Perf', | |
40 'shards': [2] | |
41 } | |
42 # crbug.com/663762 | |
43 #{ | |
44 # 'name': 'Android Nexus9 Perf', | |
45 # 'shards': [2] | |
46 #} | |
47 ], | |
48 } | |
49 }, | |
50 { | |
51 'args': [ | |
52 'cc_perftests', | |
53 '--adb-path', | |
54 'src/third_party/catapult/devil/bin/deps/linux2/x86_64/bin/adb', | |
55 ], | |
56 'name': 'cc_perftests', | |
57 'script': 'gtest_perf_test.py', | |
58 'testers': { | |
59 'chromium.perf': [ | |
60 # crbug.com/698831 | |
61 # { | |
62 # 'name': 'Android Nexus5 Perf', | |
63 # 'shards': [2] | |
64 # }, | |
65 # { | |
66 # 'name': 'Android Nexus6 Perf', | |
67 # 'shards': [2] | |
68 # }, | |
69 # { | |
70 # 'name': 'Android Nexus7v2 Perf', | |
71 # 'shards': [2] | |
72 # }, | |
73 { | |
74 'name': 'Android Nexus9 Perf', | |
75 'shards': [2] | |
76 }, | |
77 ], | |
78 } | |
79 }, | |
80 { | |
81 'args': [ | |
82 'tracing_perftests', | |
83 '--adb-path', | |
84 'src/third_party/catapult/devil/bin/deps/linux2/x86_64/bin/adb', | |
85 ], | |
86 'name': 'tracing_perftests', | |
87 'script': 'gtest_perf_test.py', | |
88 'testers': { | |
89 'chromium.perf': [ | |
90 { | |
91 'name': 'Android Nexus5 Perf', | |
92 'shards': [2] | |
93 }, | |
94 { | |
95 'name': 'Android Nexus6 Perf', | |
96 'shards': [2] | |
97 }, | |
98 { | |
99 'name': 'Android Nexus7v2 Perf', | |
100 'shards': [2] | |
101 }, | |
102 { | |
103 'name': 'Android Nexus9 Perf', | |
104 'shards': [2] | |
105 }, | |
106 ] | |
107 } | |
108 }, | |
109 ] | |
110 | |
111 | |
112 def add_builder(waterfall, name, additional_compile_targets=None): | |
113 waterfall['builders'][name] = added = {} | |
114 if additional_compile_targets: | |
115 added['additional_compile_targets'] = additional_compile_targets | |
116 | |
117 return waterfall | |
118 | |
119 def add_tester(waterfall, name, perf_id, platform, target_bits=64, | |
120 num_host_shards=1, num_device_shards=1, swarming=None, | |
121 use_whitelist=False): | |
122 del perf_id # this will be needed | |
123 waterfall['testers'][name] = { | |
124 'platform': platform, | |
125 'num_device_shards': num_device_shards, | |
126 'num_host_shards': num_host_shards, | |
127 'target_bits': target_bits, | |
128 'use_whitelist': use_whitelist | |
129 } | |
130 | |
131 if swarming: | |
132 waterfall['testers'][name]['swarming_dimensions'] = swarming | |
133 waterfall['testers'][name]['swarming'] = True | |
134 | |
135 return waterfall | |
136 | |
137 | |
138 def get_fyi_waterfall_config(): | |
139 waterfall = {'builders':{}, 'testers': {}} | |
140 waterfall = add_tester( | |
141 waterfall, 'Win 10 Low-End Perf Tests', | |
142 'win-10-low-end', 'win', | |
143 swarming=[ | |
144 { | |
145 'gpu': '1002:9874', | |
146 'os': 'Windows-10-10586', | |
147 'device_ids': [ | |
148 'build171-b4', 'build186-b4', 'build202-b4', 'build203-b4', | |
149 'build204-b4', 'build205-b4', 'build206-b4', 'build207-b4', | |
150 'build208-b4', 'build209-b4', 'build210-b4', 'build211-b4', | |
151 'build212-b4', 'build213-b4', 'build214-b4', 'build215-b4', | |
152 'build216-b4', 'build217-b4', 'build218-b4', 'build219-b4', | |
153 'build220-b4', 'build221-b4'] | |
154 } | |
155 ]) | |
156 waterfall = add_tester( | |
157 waterfall, 'Win 10 4 Core Low-End Perf Tests', | |
158 'win-10-4-core-low-end', 'win', | |
159 swarming=[ | |
160 { | |
161 'gpu': '8086:22b1', | |
162 'os': 'Windows-10-10586', | |
163 'device_ids': [ | |
164 'build136-b1', 'build137-b1', 'build138-b1', 'build139-b1', | |
165 'build140-b1', 'build141-b1', 'build142-b1', 'build143-b1', | |
166 'build144-b1', 'build145-b1', 'build146-b1', 'build147-b1', | |
167 'build148-b1', 'build149-b1', 'build150-b1', 'build151-b1', | |
168 'build152-b1', 'build153-b1', 'build154-b1', 'build155-b1', | |
169 'build47-b4', 'build48-b4'], | |
170 'perf_tests': [ | |
171 ('cc_perftests', 0), | |
172 ('gpu_perftests', 0), | |
173 ('load_library_perf_tests', 0), | |
174 ('angle_perftests', 1), | |
175 ('performance_browser_tests', 1), | |
176 ('tracing_perftests', 1)] | |
177 } | |
178 ]) | |
179 waterfall = add_tester( | |
180 waterfall, 'Android Swarming N5X Tester', | |
181 'fyi-android-swarming-n5x', 'android', | |
182 swarming=[ | |
183 { | |
184 'os': 'Android', | |
185 'android_devices': '1', | |
186 'device_ids': [ | |
187 'build245-m4--device1', 'build245-m4--device2', | |
188 'build245-m4--device3', 'build245-m4--device4', | |
189 'build245-m4--device5', 'build245-m4--device6', | |
190 'build245-m4--device7', 'build248-m4--device1', | |
191 'build248-m4--device2', 'build248-m4--device3', | |
192 'build248-m4--device4', 'build248-m4--device5', | |
193 'build248-m4--device6', 'build248-m4--device7', | |
194 'build249-m4--device1', 'build249-m4--device2', | |
195 'build249-m4--device3', 'build249-m4--device4', | |
196 'build249-m4--device5', 'build249-m4--device6', | |
197 'build249-m4--device7' | |
198 ] | |
199 } | |
200 ]) | |
201 return waterfall | |
202 | |
203 | |
204 def get_waterfall_config(): | |
205 waterfall = {'builders':{}, 'testers': {}} | |
206 | |
207 waterfall = add_builder( | |
208 waterfall, 'Android Compile', additional_compile_targets=[ | |
209 'microdump_stackwalk' | |
210 ]) | |
211 waterfall = add_builder( | |
212 waterfall, 'Android arm64 Compile', additional_compile_targets=[ | |
213 'microdump_stackwalk' | |
214 ]) | |
215 | |
216 # These configurations are taken from chromium_perf.py in | |
217 # build/scripts/slave/recipe_modules/chromium_tests and must be kept in sync | |
218 # to generate the correct json for each tester | |
219 waterfall = add_tester( | |
220 waterfall, 'Android Nexus5 Perf', 'android-nexus5', | |
221 'android', target_bits=32, num_device_shards=7, num_host_shards=3) | |
222 waterfall = add_tester( | |
223 waterfall, 'Android Nexus5X Perf', 'android-nexus5X', | |
224 'android', target_bits=32, num_device_shards=7, num_host_shards=3) | |
225 waterfall = add_tester( | |
226 waterfall, 'Android Nexus6 Perf', 'android-nexus6', | |
227 'android', target_bits=32, num_device_shards=7, num_host_shards=3) | |
228 waterfall = add_tester( | |
229 waterfall, 'Android Nexus7v2 Perf', 'android-nexus7v2', | |
230 'android', target_bits=32, num_device_shards=7, num_host_shards=3) | |
231 waterfall = add_tester( | |
232 waterfall, 'Android One Perf', 'android-one', | |
233 'android', target_bits=32, num_device_shards=7, num_host_shards=3) | |
234 | |
235 waterfall = add_tester( | |
236 waterfall, 'Win Zenbook Perf', 'win-zenbook', 'win', | |
237 swarming=[ | |
238 { | |
239 'gpu': '8086:161e', | |
240 'os': 'Windows-10-10240', | |
241 'device_ids': [ | |
242 'build30-b1', 'build31-b1', | |
243 'build32-b1', 'build33-b1', 'build34-b1' | |
244 ] | |
245 } | |
246 ]) | |
247 waterfall = add_tester( | |
248 waterfall, 'Win 10 High-DPI Perf', 'win-high-dpi', 'win', | |
249 swarming=[ | |
250 { | |
251 'gpu': '8086:1616', | |
252 'os': 'Windows-10-10240', | |
253 'device_ids': [ | |
254 'build117-b1', 'build118-b1', | |
255 'build119-b1', 'build120-b1', 'build121-b1' | |
256 ] | |
257 } | |
258 ]) | |
259 waterfall = add_tester( | |
260 waterfall, 'Win 10 Perf', 'chromium-rel-win10', 'win', | |
261 swarming=[ | |
262 { | |
263 'gpu': '102b:0534', | |
264 'os': 'Windows-10-10240', | |
265 'device_ids': [ | |
266 'build132-m1', 'build133-m1', | |
267 'build134-m1', 'build135-m1', 'build136-m1' | |
268 ], | |
269 'perf_tests': [ | |
270 ('media_perftests', 2)] | |
271 } | |
272 ]) | |
273 waterfall = add_tester( | |
274 waterfall, 'Win 8 Perf', 'chromium-rel-win8-dual', 'win', | |
275 swarming=[ | |
276 { | |
277 'gpu': '102b:0532', | |
278 'os': 'Windows-2012ServerR2-SP0', | |
279 'device_ids': [ | |
280 'build143-m1', 'build144-m1', | |
281 'build145-m1', 'build146-m1', 'build147-m1' | |
282 ], | |
283 'perf_tests': [ | |
284 ('load_library_perf_tests', 2), | |
285 ('performance_browser_tests', 2), | |
286 ('media_perftests', 3)] | |
287 } | |
288 ]) | |
289 waterfall = add_tester( | |
290 waterfall, 'Win 7 Perf', 'chromium-rel-win7-dual', | |
291 'win', target_bits=32, | |
292 swarming=[ | |
293 { | |
294 'gpu': '102b:0532', | |
295 'os': 'Windows-2008ServerR2-SP1', | |
296 'device_ids': [ | |
297 'build185-m1', 'build186-m1', | |
298 'build187-m1', 'build188-m1', 'build189-m1' | |
299 ], | |
300 'perf_tests': [ | |
301 ('load_library_perf_tests', 2), | |
302 ('performance_browser_tests', 2), | |
303 ('media_perftests', 3)] | |
304 } | |
305 ]) | |
306 waterfall = add_tester( | |
307 waterfall, 'Win 7 x64 Perf', | |
308 'chromium-rel-win7-x64-dual', 'win', | |
309 swarming=[ | |
310 { | |
311 'gpu': '102b:0532', | |
312 'os': 'Windows-2008ServerR2-SP1', | |
313 'device_ids': [ | |
314 'build138-m1', 'build139-m1', | |
315 'build140-m1', 'build141-m1', 'build142-m1' | |
316 ], | |
317 'perf_tests': [ | |
318 ('load_library_perf_tests', 2), | |
319 ('performance_browser_tests', 2)] | |
320 } | |
321 ]) | |
322 waterfall = add_tester( | |
323 waterfall, 'Win 7 ATI GPU Perf', | |
324 'chromium-rel-win7-gpu-ati', 'win', | |
325 swarming=[ | |
326 { | |
327 'gpu': '1002:6613', | |
328 'os': 'Windows-2008ServerR2-SP1', | |
329 'device_ids': [ | |
330 'build101-m1', 'build102-m1', | |
331 'build103-m1', 'build104-m1', 'build105-m1' | |
332 ], | |
333 'perf_tests': [ | |
334 ('angle_perftests', 2), | |
335 ('load_library_perf_tests', 2), | |
336 ('performance_browser_tests', 2), | |
337 ('media_perftests', 3)] | |
338 } | |
339 ]) | |
340 waterfall = add_tester( | |
341 waterfall, 'Win 7 Intel GPU Perf', | |
342 'chromium-rel-win7-gpu-intel', 'win', | |
343 swarming=[ | |
344 { | |
345 'gpu': '8086:041a', | |
346 'os': 'Windows-2008ServerR2-SP1', | |
347 'device_ids': [ | |
348 'build164-m1', 'build165-m1', | |
349 'build166-m1', 'build167-m1', 'build168-m1' | |
350 ], | |
351 'perf_tests': [ | |
352 ('angle_perftests', 2), | |
353 ('load_library_perf_tests', 2), | |
354 ('performance_browser_tests', 2)] | |
355 } | |
356 ]) | |
357 waterfall = add_tester( | |
358 waterfall, 'Win 7 Nvidia GPU Perf', | |
359 'chromium-rel-win7-gpu-nvidia', 'win', | |
360 swarming=[ | |
361 { | |
362 'gpu': '10de:104a', | |
363 'os': 'Windows-2008ServerR2-SP1', | |
364 'device_ids': [ | |
365 'build92-m1', 'build93-m1', | |
366 'build94-m1', 'build95-m1', 'build96-m1' | |
367 ], | |
368 'perf_tests': [ | |
369 ('angle_perftests', 2), | |
370 ('load_library_perf_tests', 2), | |
371 ('performance_browser_tests', 2), | |
372 ('media_perftests', 3)] | |
373 } | |
374 ]) | |
375 | |
376 waterfall = add_tester( | |
377 waterfall, 'Mac 10.11 Perf', 'chromium-rel-mac11', | |
378 'mac', | |
379 swarming=[ | |
380 { | |
381 'gpu': '8086:0166', | |
382 'os': 'Mac-10.11', | |
383 'device_ids': [ | |
384 'build102-b1', 'build103-b1', | |
385 'build104-b1', 'build105-b1', 'build106-b1' | |
386 ], | |
387 'perf_tests': [ | |
388 ('media_perftests', 3)] | |
389 } | |
390 ]) | |
391 waterfall = add_tester( | |
392 waterfall, 'Mac 10.12 Perf', 'chromium-rel-mac12', | |
393 'mac', | |
394 swarming=[ | |
395 { | |
396 'os': 'Mac-10.12', | |
397 'gpu': '8086:0a2e', | |
398 'device_ids': [ | |
399 'build158-m1', 'build159-m1', 'build160-m1', | |
400 'build161-m1', 'build162-m1'] | |
401 } | |
402 ]) | |
403 waterfall = add_tester( | |
404 waterfall, 'Mac Retina Perf', | |
405 'chromium-rel-mac-retina', 'mac', | |
406 swarming=[ | |
407 { | |
408 'gpu': '8086:0d26', | |
409 'os': 'Mac-10.11', | |
410 'device_ids': [ | |
411 'build4-b1', 'build5-b1', 'build6-b1', 'build7-b1', 'build8-b1' | |
412 ] | |
413 } | |
414 ]) | |
415 waterfall = add_tester( | |
416 waterfall, 'Mac Pro 10.11 Perf', | |
417 'chromium-rel-mac11-pro', 'mac', | |
418 swarming=[ | |
419 { | |
420 'gpu': '1002:6821', | |
421 'os': 'Mac-10.11', | |
422 'device_ids': [ | |
423 'build128-b1', 'build129-b1', | |
424 'build130-b1', 'build131-b1', 'build132-b1' | |
425 ] | |
426 } | |
427 ]) | |
428 waterfall = add_tester( | |
429 waterfall, 'Mac Air 10.11 Perf', | |
430 'chromium-rel-mac11-air', 'mac', | |
431 swarming=[ | |
432 { | |
433 'gpu': '8086:1626', | |
434 'os': 'Mac-10.11', | |
435 'device_ids': [ | |
436 'build123-b1', 'build124-b1', | |
437 'build125-b1', 'build126-b1', 'build127-b1' | |
438 ] | |
439 } | |
440 ]) | |
441 waterfall = add_tester( | |
442 waterfall, 'Mac Mini 8GB 10.12 Perf', | |
443 'chromium-rel-mac12-mini-8gb', 'mac', | |
444 swarming=[ | |
445 { | |
446 'gpu': '8086:0a26', | |
447 'os': 'Mac-10.12', | |
448 'device_ids': [ | |
449 'build24-b1', 'build25-b1', | |
450 'build26-b1', 'build27-b1', 'build28-b1' | |
451 ] | |
452 } | |
453 ]) | |
454 | |
455 waterfall = add_tester( | |
456 waterfall, 'Linux Perf', 'linux-release', 'linux', | |
457 swarming=[ | |
458 { | |
459 'gpu': '102b:0534', | |
460 'os': 'Ubuntu-14.04', | |
461 'device_ids': [ | |
462 'build148-m1', 'build149-m1', | |
463 'build150-m1', 'build151-m1', 'build152-m1' | |
464 ], | |
465 'perf_tests': [ | |
466 # crbug.com/698831 | |
467 # ('cc_perftests', 2), | |
468 ('load_library_perf_tests', 2), | |
469 ('tracing_perftests', 2), | |
470 ('media_perftests', 3)] | |
471 } | |
472 ]) | |
473 | |
474 return waterfall | |
475 | |
476 | |
477 def generate_isolate_script_entry(swarming_dimensions, test_args, | |
478 isolate_name, step_name, override_compile_targets=None, | |
479 swarming_timeout=None): | |
480 result = { | |
481 'args': test_args, | |
482 'isolate_name': isolate_name, | |
483 'name': step_name, | |
484 } | |
485 if override_compile_targets: | |
486 result['override_compile_targets'] = override_compile_targets | |
487 if swarming_dimensions: | |
488 result['swarming'] = { | |
489 # Always say this is true regardless of whether the tester | |
490 # supports swarming. It doesn't hurt. | |
491 'can_use_on_swarming_builders': True, | |
492 'expiration': 21600, | |
493 'hard_timeout': swarming_timeout if swarming_timeout else 7200, | |
494 'io_timeout': 3600, | |
495 'dimension_sets': swarming_dimensions, | |
496 } | |
497 return result | |
498 | |
499 | |
500 def generate_telemetry_test(swarming_dimensions, benchmark_name, browser): | |
501 # The step name must end in 'test' or 'tests' in order for the | |
502 # results to automatically show up on the flakiness dashboard. | |
503 # (At least, this was true some time ago.) Continue to use this | |
504 # naming convention for the time being to minimize changes. | |
505 | |
506 test_args = [ | |
507 benchmark_name, | |
508 '-v', | |
509 '--upload-results', | |
510 '--output-format=chartjson', | |
511 '--browser=%s' % browser | |
512 ] | |
513 # When this is enabled on more than just windows machines we will need | |
514 # --device=android | |
515 | |
516 step_name = benchmark_name | |
517 if browser == 'reference': | |
518 test_args.append('--output-trace-tag=_ref') | |
519 step_name += '.reference' | |
520 | |
521 return generate_isolate_script_entry( | |
522 swarming_dimensions, test_args, 'telemetry_perf_tests', | |
523 step_name, ['telemetry_perf_tests'], | |
524 swarming_timeout=BENCHMARK_SWARMING_TIMEOUTS.get(benchmark_name)) | |
525 | |
526 | |
527 def script_test_enabled_on_tester(master, test, tester_name, shard): | |
528 for enabled_tester in test['testers'].get(master, []): | |
529 if enabled_tester['name'] == tester_name: | |
530 if shard in enabled_tester['shards']: | |
531 return True | |
532 return False | |
533 | |
534 | |
535 def generate_script_tests(master, tester_name, shard): | |
536 script_tests = [] | |
537 for test in SCRIPT_TESTS: | |
538 if script_test_enabled_on_tester(master, test, tester_name, shard): | |
539 script = { | |
540 'args': test['args'], | |
541 'name': test['name'], | |
542 'script': test['script'] | |
543 } | |
544 script_tests.append(script) | |
545 return script_tests | |
546 | |
547 | |
548 def get_swarming_dimension(dimension, device_affinity): | |
549 complete_dimension = { | |
550 'id': dimension['device_ids'][device_affinity], | |
551 'os': dimension['os'], | |
552 'pool': 'Chrome-perf', | |
553 } | |
554 if 'gpu' in dimension: | |
555 complete_dimension['gpu'] = dimension['gpu'] | |
556 if 'android_devices' in dimension: | |
557 complete_dimension['android_devices'] = dimension['android_devices'] | |
558 return complete_dimension | |
559 | |
560 | |
561 def generate_cplusplus_isolate_script_test(dimension): | |
562 return [ | |
563 generate_isolate_script_entry( | |
564 [get_swarming_dimension(dimension, shard)], [], name, name) | |
565 for name, shard in dimension['perf_tests'] | |
566 ] | |
567 | |
568 | |
569 def generate_telemetry_tests( | |
570 tester_config, benchmarks, benchmark_sharding_map, use_whitelist): | |
571 isolated_scripts = [] | |
572 # First determine the browser that you need based on the tester | |
573 browser_name = '' | |
574 if tester_config['platform'] == 'android': | |
575 browser_name = 'android-chromium' | |
576 elif (tester_config['platform'] == 'win' | |
577 and tester_config['target_bits'] == 64): | |
578 browser_name = 'release_x64' | |
579 else: | |
580 browser_name ='release' | |
581 | |
582 num_shards = len(tester_config['swarming_dimensions'][0]['device_ids']) | |
583 current_shard = 0 | |
584 for benchmark in benchmarks: | |
585 # First figure out swarming dimensions this test needs to be triggered on. | |
586 # For each set of dimensions it is only triggered on one of the devices | |
587 swarming_dimensions = [] | |
588 for dimension in tester_config['swarming_dimensions']: | |
589 device_affinity = None | |
590 if benchmark_sharding_map: | |
591 sharding_map = benchmark_sharding_map.get(str(num_shards), None) | |
592 if not sharding_map and not use_whitelist: | |
593 raise Exception('Invalid number of shards, generate new sharding map') | |
594 if use_whitelist: | |
595 device_affinity = current_shard | |
596 else: | |
597 device_affinity = sharding_map.get(benchmark.Name(), None) | |
598 else: | |
599 # No sharding map was provided, default to legacy device | |
600 # affinity algorithm | |
601 device_affinity = bot_utils.GetDeviceAffinity( | |
602 num_shards, benchmark.Name()) | |
603 if device_affinity is None: | |
604 raise Exception('Device affinity for benchmark %s not found' | |
605 % benchmark.Name()) | |
606 swarming_dimensions.append( | |
607 get_swarming_dimension(dimension, device_affinity)) | |
608 | |
609 test = generate_telemetry_test( | |
610 swarming_dimensions, benchmark.Name(), browser_name) | |
611 isolated_scripts.append(test) | |
612 # Now create another executable for this benchmark on the reference browser | |
613 reference_test = generate_telemetry_test( | |
614 swarming_dimensions, benchmark.Name(),'reference') | |
615 isolated_scripts.append(reference_test) | |
616 if current_shard == (num_shards - 1): | |
617 current_shard = 0 | |
618 else: | |
619 current_shard += 1 | |
620 | |
621 return isolated_scripts | |
622 | |
623 | |
624 BENCHMARK_NAME_WHITELIST = set([ | |
625 u'smoothness.top_25_smooth', | |
626 u'sunspider', | |
627 u'system_health.webview_startup', | |
628 u'page_cycler_v2.intl_hi_ru', | |
629 u'dromaeo.cssqueryjquery', | |
630 ]) | |
631 | |
632 # List of benchmarks that are to never be run on a waterfall. | |
633 BENCHMARK_NAME_BLACKLIST = [ | |
634 'multipage_skpicture_printer', | |
635 'multipage_skpicture_printer_ct', | |
636 'rasterize_and_record_micro_ct', | |
637 'repaint_ct', | |
638 'multipage_skpicture_printer', | |
639 'multipage_skpicture_printer_ct', | |
640 'skpicture_printer', | |
641 'skpicture_printer_ct', | |
642 ] | |
643 | |
644 # Overrides the default 2 hour timeout for swarming tasks. | |
645 BENCHMARK_SWARMING_TIMEOUTS = { | |
646 'loading.mobile': 14400, | |
647 } | |
648 | |
649 # Certain swarming bots are not sharding correctly with the new device affinity | |
650 # algorithm. Reverting to legacy algorithm to try and get them to complete. | |
651 # See crbug.com/670284 | |
652 LEGACY_DEVICE_AFFIINITY_ALGORITHM = [ | |
653 'Win Zenbook Perf', | |
654 'Win 10 High-DPI Perf', | |
655 ] | |
656 | |
657 def current_benchmarks(use_whitelist): | |
658 benchmarks_dir = os.path.join(src_dir(), 'tools', 'perf', 'benchmarks') | |
659 top_level_dir = os.path.dirname(benchmarks_dir) | |
660 | |
661 all_benchmarks = discover.DiscoverClasses( | |
662 benchmarks_dir, top_level_dir, benchmark_module.Benchmark, | |
663 index_by_class_name=True).values() | |
664 # Remove all blacklisted benchmarks | |
665 for blacklisted in BENCHMARK_NAME_BLACKLIST: | |
666 for benchmark in all_benchmarks: | |
667 if benchmark.Name() == blacklisted: | |
668 all_benchmarks.remove(benchmark) | |
669 break | |
670 | |
671 if use_whitelist: | |
672 all_benchmarks = ( | |
673 bench for bench in all_benchmarks | |
674 if bench.Name() in BENCHMARK_NAME_WHITELIST) | |
675 return sorted(all_benchmarks, key=lambda b: b.Name()) | |
676 | |
677 | |
678 # Returns a sorted list of (benchmark, avg_runtime) pairs for every | |
679 # benchmark in the all_benchmarks list where avg_runtime is in seconds. Also | |
680 # returns a list of benchmarks whose run time have not been seen before | |
681 def get_sorted_benchmark_list_by_time(all_benchmarks): | |
682 runtime_list = [] | |
683 benchmark_avgs = {} | |
684 new_benchmarks = [] | |
685 timing_file_path = os.path.join(src_dir(), 'tools', 'perf', 'core', | |
686 'desktop_benchmark_avg_times.json') | |
687 # Load in the avg times as calculated on Nov 1st, 2016 | |
688 with open(timing_file_path) as f: | |
689 benchmark_avgs = json.load(f) | |
690 | |
691 for benchmark in all_benchmarks: | |
692 benchmark_avg_time = benchmark_avgs.get(benchmark.Name(), None) | |
693 if benchmark_avg_time is None: | |
694 # Assume that this is a new benchmark that was added after 11/1/16 when | |
695 # we generated the benchmarks. Use the old affinity algorithm after | |
696 # we have given the rest the same distribution, add it to the | |
697 # new benchmarks list. | |
698 new_benchmarks.append(benchmark) | |
699 else: | |
700 # Need to multiple the seconds by 2 since we will be generating two tests | |
701 # for each benchmark to be run on the same shard for the reference build | |
702 runtime_list.append((benchmark, benchmark_avg_time * 2.0)) | |
703 | |
704 # Return a reverse sorted list by runtime | |
705 runtime_list.sort(key=lambda tup: tup[1], reverse=True) | |
706 return runtime_list, new_benchmarks | |
707 | |
708 | |
709 # Returns a map of benchmark name to shard it is on. | |
710 def shard_benchmarks(num_shards, all_benchmarks): | |
711 benchmark_to_shard_dict = {} | |
712 shard_execution_times = [0] * num_shards | |
713 sorted_benchmark_list, new_benchmarks = get_sorted_benchmark_list_by_time( | |
714 all_benchmarks) | |
715 # Iterate over in reverse order and add them to the current smallest bucket. | |
716 for benchmark in sorted_benchmark_list: | |
717 # Find current smallest bucket | |
718 min_index = shard_execution_times.index(min(shard_execution_times)) | |
719 benchmark_to_shard_dict[benchmark[0].Name()] = min_index | |
720 shard_execution_times[min_index] += benchmark[1] | |
721 # For all the benchmarks that didn't have avg run times, use the default | |
722 # device affinity algorithm | |
723 for benchmark in new_benchmarks: | |
724 device_affinity = bot_utils.GetDeviceAffinity(num_shards, benchmark.Name()) | |
725 benchmark_to_shard_dict[benchmark.Name()] = device_affinity | |
726 return benchmark_to_shard_dict | |
727 | |
728 | |
729 def generate_all_tests(waterfall): | |
730 tests = {} | |
731 | |
732 all_benchmarks = current_benchmarks(False) | |
733 whitelist_benchmarks = current_benchmarks(True) | |
734 # Get benchmark sharding according to common sharding configurations | |
735 # Currently we only have bots sharded 5 directions and 1 direction | |
736 benchmark_sharding_map = {} | |
737 benchmark_sharding_map['22'] = shard_benchmarks(22, all_benchmarks) | |
738 benchmark_sharding_map['5'] = shard_benchmarks(5, all_benchmarks) | |
739 benchmark_sharding_map['1'] = shard_benchmarks(1, all_benchmarks) | |
740 benchmark_sharding_map['21'] = shard_benchmarks(21, all_benchmarks) | |
741 | |
742 for name, config in waterfall['testers'].iteritems(): | |
743 use_whitelist = config['use_whitelist'] | |
744 benchmark_list = all_benchmarks | |
745 if use_whitelist: | |
746 benchmark_list = whitelist_benchmarks | |
747 if config.get('swarming', False): | |
748 # Our current configuration only ever has one set of swarming dimensions | |
749 # Make sure this still holds true | |
750 if len(config['swarming_dimensions']) > 1: | |
751 raise Exception('Invalid assumption on number of swarming dimensions') | |
752 # Generate benchmarks | |
753 sharding_map = benchmark_sharding_map | |
754 if name in LEGACY_DEVICE_AFFIINITY_ALGORITHM: | |
755 sharding_map = None | |
756 isolated_scripts = generate_telemetry_tests( | |
757 config, benchmark_list, sharding_map, use_whitelist) | |
758 # Generate swarmed non-telemetry tests if present | |
759 if config['swarming_dimensions'][0].get('perf_tests', False): | |
760 isolated_scripts += generate_cplusplus_isolate_script_test( | |
761 config['swarming_dimensions'][0]) | |
762 tests[name] = { | |
763 'isolated_scripts': sorted(isolated_scripts, key=lambda x: x['name']) | |
764 } | |
765 else: | |
766 # scripts are only currently run in addition to the main waterfall. They | |
767 # are currently the only thing generated in the perf json file. | |
768 # TODO eyaich: will need to handle the sharding differently when we have | |
769 # swarmed bots on the main waterfall. | |
770 for shard in range(0, config['num_host_shards']): | |
771 tester_name = '%s (%d)' % (name, shard + 1) | |
772 scripts = generate_script_tests(waterfall['name'], name, shard + 1) | |
773 if scripts: | |
774 tests[tester_name] = { | |
775 'scripts': sorted(scripts, key=lambda x: x['name']) | |
776 } | |
777 | |
778 for name, config in waterfall['builders'].iteritems(): | |
779 tests[name] = config | |
780 | |
781 tests['AAAAA1 AUTOGENERATED FILE DO NOT EDIT'] = {} | |
782 tests['AAAAA2 See //tools/perf/generate_perf_json.py to make changes'] = {} | |
783 return tests | |
784 | |
785 | |
786 def get_json_config_file_for_waterfall(waterfall): | |
787 filename = '%s.json' % waterfall['name'] | |
788 buildbot_dir = os.path.join(src_dir(), 'testing', 'buildbot') | |
789 return os.path.join(buildbot_dir, filename) | |
790 | |
791 | |
792 def tests_are_up_to_date(waterfall): | |
793 tests = generate_all_tests(waterfall) | |
794 tests_data = json.dumps(tests, indent=2, separators=(',', ': '), | |
795 sort_keys=True) | |
796 config_file = get_json_config_file_for_waterfall(waterfall) | |
797 with open(config_file, 'r') as fp: | |
798 config_data = fp.read().strip() | |
799 return tests_data == config_data | |
800 | |
801 | |
802 def update_all_tests(waterfall): | |
803 tests = generate_all_tests(waterfall) | |
804 config_file = get_json_config_file_for_waterfall(waterfall) | |
805 with open(config_file, 'w') as fp: | |
806 json.dump(tests, fp, indent=2, separators=(',', ': '), sort_keys=True) | |
807 fp.write('\n') | |
808 | |
809 | |
810 def src_dir(): | |
811 file_path = os.path.abspath(__file__) | |
812 return os.path.dirname(os.path.dirname( | |
813 os.path.dirname(os.path.dirname(file_path)))) | |
814 | |
815 | |
816 def main(args): | |
817 parser = argparse.ArgumentParser( | |
818 description=('Generate perf test\' json config. This need to be done ' | |
819 'anytime you add/remove any existing benchmarks in ' | |
820 'tools/perf/benchmarks.')) | |
821 parser.add_argument( | |
822 '--validate-only', action='store_true', default=False, | |
823 help=('Validate whether the perf json generated will be the same as the ' | |
824 'existing configs. This does not change the contain of existing ' | |
825 'configs')) | |
826 options = parser.parse_args(args) | |
827 | |
828 waterfall = get_waterfall_config() | |
829 waterfall['name'] = 'chromium.perf' | |
830 fyi_waterfall = get_fyi_waterfall_config() | |
831 fyi_waterfall['name'] = 'chromium.perf.fyi' | |
832 | |
833 if options.validate_only: | |
834 if tests_are_up_to_date(fyi_waterfall) and tests_are_up_to_date(waterfall): | |
835 print 'All the perf JSON config files are up-to-date. \\o/' | |
836 return 0 | |
837 else: | |
838 print ('The perf JSON config files are not up-to-date. Please run %s ' | |
839 'without --validate-only flag to update the perf JSON ' | |
840 'configs.') % sys.argv[0] | |
841 return 1 | |
842 else: | |
843 update_all_tests(fyi_waterfall) | |
844 update_all_tests(waterfall) | |
845 return 0 | |
OLD | NEW |