1#!/usr/bin/env vpython 2# 3# Copyright 2021 The ANGLE Project Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6# 7# process_angle_perf_results.py: 8# Perf result merging and upload. Adapted from the Chromium script: 9# https://chromium.googlesource.com/chromium/src/+/main/tools/perf/process_perf_results.py 10 11from __future__ import print_function 12 13import argparse 14import collections 15import json 16import logging 17import multiprocessing 18import os 19import shutil 20import sys 21import tempfile 22import time 23import uuid 24 25logging.basicConfig( 26 level=logging.INFO, 27 format='(%(levelname)s) %(asctime)s pid=%(process)d' 28 ' %(module)s.%(funcName)s:%(lineno)d %(message)s') 29 30d = os.path.dirname 31ANGLE_DIR = d(d(os.path.realpath(__file__))) 32sys.path.append(os.path.join(ANGLE_DIR, 'tools', 'perf')) 33import cross_device_test_config 34 35from core import path_util 36 37path_util.AddTelemetryToPath() 38from core import upload_results_to_perf_dashboard 39from core import bot_platforms 40from core import results_merger 41 42path_util.AddAndroidPylibToPath() 43try: 44 from pylib.utils import logdog_helper 45except ImportError: 46 pass 47 48path_util.AddTracingToPath() 49from tracing.value import histogram 50from tracing.value import histogram_set 51from tracing.value.diagnostics import generic_set 52from tracing.value.diagnostics import reserved_infos 53 54RESULTS_URL = 'https://chromeperf.appspot.com' 55JSON_CONTENT_TYPE = 'application/json' 56MACHINE_GROUP = 'ANGLE' 57BUILD_URL = 'https://ci.chromium.org/ui/p/angle/builders/ci/%s/%d' 58 59 60def _upload_perf_results(json_to_upload, name, configuration_name, build_properties, 61 output_json_file): 62 """Upload the contents of result JSON(s) to the perf dashboard.""" 63 args = [ 64 '--buildername', 65 build_properties['buildername'], 66 '--buildnumber', 67 build_properties['buildnumber'], 68 '--name', 69 name, 70 '--configuration-name', 71 configuration_name, 72 '--results-file', 73 json_to_upload, 74 '--results-url', 75 RESULTS_URL, 76 '--output-json-file', 77 output_json_file, 78 '--perf-dashboard-machine-group', 79 MACHINE_GROUP, 80 '--got-angle-revision', 81 build_properties['got_angle_revision'], 82 '--send-as-histograms', 83 '--project', 84 'angle', 85 ] 86 87 if build_properties.get('git_revision'): 88 args.append('--git-revision') 89 args.append(build_properties['git_revision']) 90 91 #TODO(crbug.com/1072729): log this in top level 92 logging.info('upload_results_to_perf_dashboard: %s.' % args) 93 94 return upload_results_to_perf_dashboard.main(args) 95 96 97def _merge_json_output(output_json, jsons_to_merge, extra_links, test_cross_device=False): 98 """Merges the contents of one or more results JSONs. 99 100 Args: 101 output_json: A path to a JSON file to which the merged results should be 102 written. 103 jsons_to_merge: A list of JSON files that should be merged. 104 extra_links: a (key, value) map in which keys are the human-readable strings 105 which describe the data, and value is logdog url that contain the data. 106 """ 107 begin_time = time.time() 108 merged_results = results_merger.merge_test_results(jsons_to_merge, test_cross_device) 109 110 # Only append the perf results links if present 111 if extra_links: 112 merged_results['links'] = extra_links 113 114 with open(output_json, 'w') as f: 115 json.dump(merged_results, f) 116 117 end_time = time.time() 118 print_duration('Merging json test results', begin_time, end_time) 119 return 0 120 121 122def _handle_perf_json_test_results(benchmark_directory_map, test_results_list): 123 """Checks the test_results.json under each folder: 124 125 1. mark the benchmark 'enabled' if tests results are found 126 2. add the json content to a list for non-ref. 127 """ 128 begin_time = time.time() 129 benchmark_enabled_map = {} 130 for benchmark_name, directories in benchmark_directory_map.items(): 131 for directory in directories: 132 # Obtain the test name we are running 133 is_ref = '.reference' in benchmark_name 134 enabled = True 135 try: 136 with open(os.path.join(directory, 'test_results.json')) as json_data: 137 json_results = json.load(json_data) 138 if not json_results: 139 # Output is null meaning the test didn't produce any results. 140 # Want to output an error and continue loading the rest of the 141 # test results. 142 logging.warning('No results produced for %s, skipping upload' % directory) 143 continue 144 if json_results.get('version') == 3: 145 # Non-telemetry tests don't have written json results but 146 # if they are executing then they are enabled and will generate 147 # chartjson results. 148 if not bool(json_results.get('tests')): 149 enabled = False 150 if not is_ref: 151 # We don't need to upload reference build data to the 152 # flakiness dashboard since we don't monitor the ref build 153 test_results_list.append(json_results) 154 except IOError as e: 155 # TODO(crbug.com/936602): Figure out how to surface these errors. Should 156 # we have a non-zero exit code if we error out? 157 logging.error('Failed to obtain test results for %s: %s', benchmark_name, e) 158 continue 159 if not enabled: 160 # We don't upload disabled benchmarks or tests that are run 161 # as a smoke test 162 logging.info('Benchmark %s ran no tests on at least one shard' % benchmark_name) 163 continue 164 benchmark_enabled_map[benchmark_name] = True 165 166 end_time = time.time() 167 print_duration('Analyzing perf json test results', begin_time, end_time) 168 return benchmark_enabled_map 169 170 171def _generate_unique_logdog_filename(name_prefix): 172 return name_prefix + '_' + str(uuid.uuid4()) 173 174 175def _handle_perf_logs(benchmark_directory_map, extra_links): 176 """ Upload benchmark logs to logdog and add a page entry for them. """ 177 begin_time = time.time() 178 benchmark_logs_links = collections.defaultdict(list) 179 180 for benchmark_name, directories in benchmark_directory_map.items(): 181 for directory in directories: 182 benchmark_log_file = os.path.join(directory, 'benchmark_log.txt') 183 if os.path.exists(benchmark_log_file): 184 with open(benchmark_log_file) as f: 185 uploaded_link = logdog_helper.text( 186 name=_generate_unique_logdog_filename(benchmark_name), data=f.read()) 187 benchmark_logs_links[benchmark_name].append(uploaded_link) 188 189 logdog_file_name = _generate_unique_logdog_filename('Benchmarks_Logs') 190 logdog_stream = logdog_helper.text( 191 logdog_file_name, 192 json.dumps(benchmark_logs_links, sort_keys=True, indent=4, separators=(',', ': ')), 193 content_type=JSON_CONTENT_TYPE) 194 extra_links['Benchmarks logs'] = logdog_stream 195 end_time = time.time() 196 print_duration('Generating perf log streams', begin_time, end_time) 197 198 199def _handle_benchmarks_shard_map(benchmarks_shard_map_file, extra_links): 200 begin_time = time.time() 201 with open(benchmarks_shard_map_file) as f: 202 benchmarks_shard_data = f.read() 203 logdog_file_name = _generate_unique_logdog_filename('Benchmarks_Shard_Map') 204 logdog_stream = logdog_helper.text( 205 logdog_file_name, benchmarks_shard_data, content_type=JSON_CONTENT_TYPE) 206 extra_links['Benchmarks shard map'] = logdog_stream 207 end_time = time.time() 208 print_duration('Generating benchmark shard map stream', begin_time, end_time) 209 210 211def _get_benchmark_name(directory): 212 return os.path.basename(directory).replace(" benchmark", "") 213 214 215def _scan_output_dir(task_output_dir): 216 benchmark_directory_map = {} 217 benchmarks_shard_map_file = None 218 219 directory_list = [ 220 f for f in os.listdir(task_output_dir) 221 if not os.path.isfile(os.path.join(task_output_dir, f)) 222 ] 223 benchmark_directory_list = [] 224 for directory in directory_list: 225 for f in os.listdir(os.path.join(task_output_dir, directory)): 226 path = os.path.join(task_output_dir, directory, f) 227 if os.path.isdir(path): 228 benchmark_directory_list.append(path) 229 elif path.endswith('benchmarks_shard_map.json'): 230 benchmarks_shard_map_file = path 231 # Now create a map of benchmark name to the list of directories 232 # the lists were written to. 233 for directory in benchmark_directory_list: 234 benchmark_name = _get_benchmark_name(directory) 235 if benchmark_name in benchmark_directory_map.keys(): 236 benchmark_directory_map[benchmark_name].append(directory) 237 else: 238 benchmark_directory_map[benchmark_name] = [directory] 239 240 return benchmark_directory_map, benchmarks_shard_map_file 241 242 243def process_perf_results(output_json, 244 configuration_name, 245 build_properties, 246 task_output_dir, 247 smoke_test_mode, 248 output_results_dir, 249 lightweight=False, 250 skip_perf=False): 251 """Process perf results. 252 253 Consists of merging the json-test-format output, uploading the perf test 254 output (histogram), and store the benchmark logs in logdog. 255 256 Each directory in the task_output_dir represents one benchmark 257 that was run. Within this directory, there is a subdirectory with the name 258 of the benchmark that was run. In that subdirectory, there is a 259 perftest-output.json file containing the performance results in histogram 260 format and an output.json file containing the json test results for the 261 benchmark. 262 263 Returns: 264 (return_code, upload_results_map): 265 return_code is 0 if the whole operation is successful, non zero otherwise. 266 benchmark_upload_result_map: the dictionary that describe which benchmarks 267 were successfully uploaded. 268 """ 269 handle_perf = not lightweight or not skip_perf 270 handle_non_perf = not lightweight or skip_perf 271 logging.info('lightweight mode: %r; handle_perf: %r; handle_non_perf: %r' % 272 (lightweight, handle_perf, handle_non_perf)) 273 274 begin_time = time.time() 275 return_code = 0 276 benchmark_upload_result_map = {} 277 278 benchmark_directory_map, benchmarks_shard_map_file = _scan_output_dir(task_output_dir) 279 280 test_results_list = [] 281 extra_links = {} 282 283 if handle_non_perf: 284 # First, upload benchmarks shard map to logdog and add a page 285 # entry for it in extra_links. 286 if benchmarks_shard_map_file: 287 _handle_benchmarks_shard_map(benchmarks_shard_map_file, extra_links) 288 289 # Second, upload all the benchmark logs to logdog and add a page entry for 290 # those links in extra_links. 291 _handle_perf_logs(benchmark_directory_map, extra_links) 292 293 # Then try to obtain the list of json test results to merge 294 # and determine the status of each benchmark. 295 benchmark_enabled_map = _handle_perf_json_test_results(benchmark_directory_map, 296 test_results_list) 297 298 build_properties_map = json.loads(build_properties) 299 if not configuration_name: 300 # we are deprecating perf-id crbug.com/817823 301 configuration_name = build_properties_map['buildername'] 302 303 _update_perf_results_for_calibration(benchmarks_shard_map_file, benchmark_enabled_map, 304 benchmark_directory_map, configuration_name) 305 if not smoke_test_mode and handle_perf: 306 try: 307 return_code, benchmark_upload_result_map = _handle_perf_results( 308 benchmark_enabled_map, benchmark_directory_map, configuration_name, 309 build_properties_map, extra_links, output_results_dir) 310 except Exception: 311 logging.exception('Error handling perf results jsons') 312 return_code = 1 313 314 if handle_non_perf: 315 # Finally, merge all test results json, add the extra links and write out to 316 # output location 317 try: 318 _merge_json_output(output_json, test_results_list, extra_links, 319 configuration_name in cross_device_test_config.TARGET_DEVICES) 320 except Exception: 321 logging.exception('Error handling test results jsons.') 322 323 end_time = time.time() 324 print_duration('Total process_perf_results', begin_time, end_time) 325 return return_code, benchmark_upload_result_map 326 327 328def _merge_histogram_results(histogram_lists): 329 merged_results = [] 330 for histogram_list in histogram_lists: 331 merged_results += histogram_list 332 333 return merged_results 334 335 336def _load_histogram_set_from_dict(data): 337 histograms = histogram_set.HistogramSet() 338 histograms.ImportDicts(data) 339 return histograms 340 341 342def _add_build_info(results, benchmark_name, build_properties): 343 histograms = _load_histogram_set_from_dict(results) 344 345 common_diagnostics = { 346 reserved_infos.MASTERS: 347 build_properties['builder_group'], 348 reserved_infos.BOTS: 349 build_properties['buildername'], 350 reserved_infos.POINT_ID: 351 build_properties['angle_commit_pos'], 352 reserved_infos.BENCHMARKS: 353 benchmark_name, 354 reserved_infos.ANGLE_REVISIONS: 355 build_properties['got_angle_revision'], 356 reserved_infos.BUILD_URLS: 357 BUILD_URL % (build_properties['buildername'], build_properties['buildnumber']), 358 } 359 360 for k, v in common_diagnostics.items(): 361 histograms.AddSharedDiagnosticToAllHistograms(k.name, generic_set.GenericSet([v])) 362 363 return histograms.AsDicts() 364 365 366def _merge_perf_results(benchmark_name, results_filename, directories, build_properties): 367 begin_time = time.time() 368 collected_results = [] 369 for directory in directories: 370 filename = os.path.join(directory, 'perf_results.json') 371 try: 372 with open(filename) as pf: 373 collected_results.append(json.load(pf)) 374 except IOError as e: 375 # TODO(crbug.com/936602): Figure out how to surface these errors. Should 376 # we have a non-zero exit code if we error out? 377 logging.error('Failed to obtain perf results from %s: %s', directory, e) 378 if not collected_results: 379 logging.error('Failed to obtain any perf results from %s.', benchmark_name) 380 return 381 382 # Assuming that multiple shards will be histogram set 383 # Non-telemetry benchmarks only ever run on one shard 384 merged_results = [] 385 assert (isinstance(collected_results[0], list)) 386 merged_results = _merge_histogram_results(collected_results) 387 388 # Write additional histogram build info. 389 merged_results = _add_build_info(merged_results, benchmark_name, build_properties) 390 391 with open(results_filename, 'w') as rf: 392 json.dump(merged_results, rf) 393 394 end_time = time.time() 395 print_duration(('%s results merging' % (benchmark_name)), begin_time, end_time) 396 397 398def _upload_individual(benchmark_name, directories, configuration_name, build_properties, 399 output_json_file): 400 tmpfile_dir = tempfile.mkdtemp() 401 try: 402 upload_begin_time = time.time() 403 # There are potentially multiple directores with results, re-write and 404 # merge them if necessary 405 results_filename = None 406 if len(directories) > 1: 407 merge_perf_dir = os.path.join(os.path.abspath(tmpfile_dir), benchmark_name) 408 if not os.path.exists(merge_perf_dir): 409 os.makedirs(merge_perf_dir) 410 results_filename = os.path.join(merge_perf_dir, 'merged_perf_results.json') 411 _merge_perf_results(benchmark_name, results_filename, directories, build_properties) 412 else: 413 # It was only written to one shard, use that shards data 414 results_filename = os.path.join(directories[0], 'perf_results.json') 415 416 results_size_in_mib = os.path.getsize(results_filename) / (2**20) 417 logging.info('Uploading perf results from %s benchmark (size %s Mib)' % 418 (benchmark_name, results_size_in_mib)) 419 with open(output_json_file, 'w') as oj: 420 upload_return_code = _upload_perf_results(results_filename, benchmark_name, 421 configuration_name, build_properties, oj) 422 upload_end_time = time.time() 423 print_duration(('%s upload time' % (benchmark_name)), upload_begin_time, 424 upload_end_time) 425 return (benchmark_name, upload_return_code == 0) 426 finally: 427 shutil.rmtree(tmpfile_dir) 428 429 430def _upload_individual_benchmark(params): 431 try: 432 return _upload_individual(*params) 433 except Exception: 434 benchmark_name = params[0] 435 upload_succeed = False 436 logging.exception('Error uploading perf result of %s' % benchmark_name) 437 return benchmark_name, upload_succeed 438 439 440def _GetCpuCount(log=True): 441 try: 442 cpu_count = multiprocessing.cpu_count() 443 if sys.platform == 'win32': 444 # TODO(crbug.com/1190269) - we can't use more than 56 445 # cores on Windows or Python3 may hang. 446 cpu_count = min(cpu_count, 56) 447 return cpu_count 448 except NotImplementedError: 449 if log: 450 logging.warn('Failed to get a CPU count for this bot. See crbug.com/947035.') 451 # TODO(crbug.com/948281): This is currently set to 4 since the mac masters 452 # only have 4 cores. Once we move to all-linux, this can be increased or 453 # we can even delete this whole function and use multiprocessing.cpu_count() 454 # directly. 455 return 4 456 457 458def _load_shard_id_from_test_results(directory): 459 shard_id = None 460 test_json_path = os.path.join(directory, 'test_results.json') 461 try: 462 with open(test_json_path) as f: 463 test_json = json.load(f) 464 all_results = test_json['tests'] 465 for _, benchmark_results in all_results.items(): 466 for _, measurement_result in benchmark_results.items(): 467 shard_id = measurement_result['shard'] 468 break 469 except IOError as e: 470 logging.error('Failed to open test_results.json from %s: %s', test_json_path, e) 471 except KeyError as e: 472 logging.error('Failed to locate results in test_results.json: %s', e) 473 return shard_id 474 475 476def _find_device_id_by_shard_id(benchmarks_shard_map_file, shard_id): 477 try: 478 with open(benchmarks_shard_map_file) as f: 479 shard_map_json = json.load(f) 480 device_id = shard_map_json['extra_infos']['bot #%s' % shard_id] 481 except KeyError as e: 482 logging.error('Failed to locate device name in shard map: %s', e) 483 return device_id 484 485 486def _update_perf_json_with_summary_on_device_id(directory, device_id): 487 perf_json_path = os.path.join(directory, 'perf_results.json') 488 try: 489 with open(perf_json_path, 'r') as f: 490 perf_json = json.load(f) 491 except IOError as e: 492 logging.error('Failed to open perf_results.json from %s: %s', perf_json_path, e) 493 summary_key_guid = str(uuid.uuid4()) 494 summary_key_generic_set = { 495 'values': ['device_id'], 496 'guid': summary_key_guid, 497 'type': 'GenericSet' 498 } 499 perf_json.insert(0, summary_key_generic_set) 500 logging.info('Inserted summary key generic set for perf result in %s: %s', directory, 501 summary_key_generic_set) 502 stories_guids = set() 503 for entry in perf_json: 504 if 'diagnostics' in entry: 505 entry['diagnostics']['summaryKeys'] = summary_key_guid 506 stories_guids.add(entry['diagnostics']['stories']) 507 for entry in perf_json: 508 if 'guid' in entry and entry['guid'] in stories_guids: 509 entry['values'].append(device_id) 510 try: 511 with open(perf_json_path, 'w') as f: 512 json.dump(perf_json, f) 513 except IOError as e: 514 logging.error('Failed to writing perf_results.json to %s: %s', perf_json_path, e) 515 logging.info('Finished adding device id %s in perf result.', device_id) 516 517 518def _should_add_device_id_in_perf_result(builder_name): 519 # We should always add device id in calibration builders. 520 # For testing purpose, adding fyi as well for faster turnaround, because 521 # calibration builders run every 24 hours. 522 return any([builder_name == p.name for p in bot_platforms.CALIBRATION_PLATFORMS 523 ]) or (builder_name == 'android-pixel2-perf-fyi') 524 525 526def _update_perf_results_for_calibration(benchmarks_shard_map_file, benchmark_enabled_map, 527 benchmark_directory_map, configuration_name): 528 if not _should_add_device_id_in_perf_result(configuration_name): 529 return 530 logging.info('Updating perf results for %s.', configuration_name) 531 for benchmark_name, directories in benchmark_directory_map.items(): 532 if not benchmark_enabled_map.get(benchmark_name, False): 533 continue 534 for directory in directories: 535 shard_id = _load_shard_id_from_test_results(directory) 536 device_id = _find_device_id_by_shard_id(benchmarks_shard_map_file, shard_id) 537 _update_perf_json_with_summary_on_device_id(directory, device_id) 538 539 540def _handle_perf_results(benchmark_enabled_map, benchmark_directory_map, configuration_name, 541 build_properties, extra_links, output_results_dir): 542 """ 543 Upload perf results to the perf dashboard. 544 545 This method also upload the perf results to logdog and augment it to 546 |extra_links|. 547 548 Returns: 549 (return_code, benchmark_upload_result_map) 550 return_code is 0 if this upload to perf dashboard successfully, 1 551 otherwise. 552 benchmark_upload_result_map is a dictionary describes which benchmark 553 was successfully uploaded. 554 """ 555 begin_time = time.time() 556 # Upload all eligible benchmarks to the perf dashboard 557 results_dict = {} 558 559 invocations = [] 560 for benchmark_name, directories in benchmark_directory_map.items(): 561 if not benchmark_enabled_map.get(benchmark_name, False): 562 continue 563 # Create a place to write the perf results that you will write out to 564 # logdog. 565 output_json_file = os.path.join(output_results_dir, (str(uuid.uuid4()) + benchmark_name)) 566 results_dict[benchmark_name] = output_json_file 567 #TODO(crbug.com/1072729): pass final arguments instead of build properties 568 # and configuration_name 569 invocations.append( 570 (benchmark_name, directories, configuration_name, build_properties, output_json_file)) 571 572 # Kick off the uploads in multiple processes 573 # crbug.com/1035930: We are hitting HTTP Response 429. Limit ourselves 574 # to 2 processes to avoid this error. Uncomment the following code once 575 # the problem is fixed on the dashboard side. 576 # pool = multiprocessing.Pool(_GetCpuCount()) 577 pool = multiprocessing.Pool(2) 578 upload_result_timeout = False 579 try: 580 async_result = pool.map_async(_upload_individual_benchmark, invocations) 581 # TODO(crbug.com/947035): What timeout is reasonable? 582 results = async_result.get(timeout=4000) 583 except multiprocessing.TimeoutError: 584 upload_result_timeout = True 585 logging.error('Timeout uploading benchmarks to perf dashboard in parallel') 586 results = [] 587 for benchmark_name in benchmark_directory_map: 588 results.append((benchmark_name, False)) 589 finally: 590 pool.terminate() 591 592 # Keep a mapping of benchmarks to their upload results 593 benchmark_upload_result_map = {} 594 for r in results: 595 benchmark_upload_result_map[r[0]] = r[1] 596 597 logdog_dict = {} 598 upload_failures_counter = 0 599 logdog_stream = None 600 logdog_label = 'Results Dashboard' 601 for benchmark_name, output_file in results_dict.items(): 602 upload_succeed = benchmark_upload_result_map[benchmark_name] 603 if not upload_succeed: 604 upload_failures_counter += 1 605 is_reference = '.reference' in benchmark_name 606 _write_perf_data_to_logfile( 607 benchmark_name, 608 output_file, 609 configuration_name, 610 build_properties, 611 logdog_dict, 612 is_reference, 613 upload_failure=not upload_succeed) 614 615 logdog_file_name = _generate_unique_logdog_filename('Results_Dashboard_') 616 logdog_stream = logdog_helper.text( 617 logdog_file_name, 618 json.dumps(dict(logdog_dict), sort_keys=True, indent=4, separators=(',', ': ')), 619 content_type=JSON_CONTENT_TYPE) 620 if upload_failures_counter > 0: 621 logdog_label += (' %s merge script perf data upload failures' % upload_failures_counter) 622 extra_links[logdog_label] = logdog_stream 623 end_time = time.time() 624 print_duration('Uploading results to perf dashboard', begin_time, end_time) 625 if upload_result_timeout or upload_failures_counter > 0: 626 return 1, benchmark_upload_result_map 627 return 0, benchmark_upload_result_map 628 629 630def _write_perf_data_to_logfile(benchmark_name, output_file, configuration_name, build_properties, 631 logdog_dict, is_ref, upload_failure): 632 viewer_url = None 633 # logdog file to write perf results to 634 if os.path.exists(output_file): 635 results = None 636 with open(output_file) as f: 637 try: 638 results = json.load(f) 639 except ValueError: 640 logging.error('Error parsing perf results JSON for benchmark %s' % benchmark_name) 641 if results: 642 try: 643 json_fname = _generate_unique_logdog_filename(benchmark_name) 644 output_json_file = logdog_helper.open_text(json_fname) 645 json.dump(results, output_json_file, indent=4, separators=(',', ': ')) 646 except ValueError as e: 647 logging.error('ValueError: "%s" while dumping output to logdog' % e) 648 finally: 649 output_json_file.close() 650 viewer_url = output_json_file.get_viewer_url() 651 else: 652 logging.warning("Perf results JSON file doesn't exist for benchmark %s" % benchmark_name) 653 654 base_benchmark_name = benchmark_name.replace('.reference', '') 655 656 if base_benchmark_name not in logdog_dict: 657 logdog_dict[base_benchmark_name] = {} 658 659 # add links for the perf results and the dashboard url to 660 # the logs section of buildbot 661 if is_ref: 662 if viewer_url: 663 logdog_dict[base_benchmark_name]['perf_results_ref'] = viewer_url 664 if upload_failure: 665 logdog_dict[base_benchmark_name]['ref_upload_failed'] = 'True' 666 else: 667 # TODO(jmadill): Figure out if we can get a dashboard URL here. http://anglebug.com/6090 668 # logdog_dict[base_benchmark_name]['dashboard_url'] = ( 669 # upload_results_to_perf_dashboard.GetDashboardUrl(benchmark_name, configuration_name, 670 # RESULTS_URL, 671 # build_properties['got_revision_cp'], 672 # _GetMachineGroup(build_properties))) 673 if viewer_url: 674 logdog_dict[base_benchmark_name]['perf_results'] = viewer_url 675 if upload_failure: 676 logdog_dict[base_benchmark_name]['upload_failed'] = 'True' 677 678 679def print_duration(step, start, end): 680 logging.info('Duration of %s: %d seconds' % (step, end - start)) 681 682 683def main(): 684 """ See collect_task.collect_task for more on the merge script API. """ 685 logging.info(sys.argv) 686 parser = argparse.ArgumentParser() 687 # configuration-name (previously perf-id) is the name of bot the tests run on 688 # For example, buildbot-test is the name of the android-go-perf bot 689 # configuration-name and results-url are set in the json file which is going 690 # away tools/perf/core/chromium.perf.fyi.extras.json 691 parser.add_argument('--configuration-name', help=argparse.SUPPRESS) 692 693 parser.add_argument('--build-properties', help=argparse.SUPPRESS) 694 parser.add_argument('--summary-json', help=argparse.SUPPRESS) 695 parser.add_argument('--task-output-dir', help=argparse.SUPPRESS) 696 parser.add_argument('-o', '--output-json', required=True, help=argparse.SUPPRESS) 697 parser.add_argument( 698 '--skip-perf', 699 action='store_true', 700 help='In lightweight mode, using --skip-perf will skip the performance' 701 ' data handling.') 702 parser.add_argument( 703 '--lightweight', 704 action='store_true', 705 help='Choose the lightweight mode in which the perf result handling' 706 ' is performed on a separate VM.') 707 parser.add_argument('json_files', nargs='*', help=argparse.SUPPRESS) 708 parser.add_argument( 709 '--smoke-test-mode', 710 action='store_true', 711 help='This test should be run in smoke test mode' 712 ' meaning it does not upload to the perf dashboard') 713 714 args = parser.parse_args() 715 716 output_results_dir = tempfile.mkdtemp('outputresults') 717 try: 718 return_code, _ = process_perf_results(args.output_json, args.configuration_name, 719 args.build_properties, args.task_output_dir, 720 args.smoke_test_mode, output_results_dir, 721 args.lightweight, args.skip_perf) 722 return return_code 723 finally: 724 shutil.rmtree(output_results_dir) 725 726 727if __name__ == '__main__': 728 sys.exit(main()) 729