summaryrefslogtreecommitdiffstats
path: root/scripts/oe-build-perf-report
diff options
context:
space:
mode:
authorMarkus Lehtonen <markus.lehtonen@linux.intel.com>2017-09-15 16:04:38 +0300
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-09-18 11:07:30 +0100
commit81aef784fdbd2e8a543475b1892c3d6a1fe97872 (patch)
treed787e9402d3fa667eee19a4447f46b440e7eda5c /scripts/oe-build-perf-report
parentb5fb3dd904cd22212c720f3c79d71952ecbaa9c2 (diff)
downloadpoky-81aef784fdbd2e8a543475b1892c3d6a1fe97872.tar.gz
scripts/oe-build-perf-report: summary of task resource usage
Utilize buildstats, if available, and show a summary of the resource usage of bitbake tasks in the html report. The details provided are: - total number of tasks - top 5 resource-hungry tasks (cputime) - top 5 increase in resource usage (cputime) - top 5 decrease in resource usage (cputime) [YOCTO #11381] (From OE-Core rev: ddd9443cb2432af2c15b358bfda708393fa3c417) Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com> Signed-off-by: Ross Burton <ross.burton@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/oe-build-perf-report')
-rwxr-xr-xscripts/oe-build-perf-report90
1 files changed, 67 insertions, 23 deletions
diff --git a/scripts/oe-build-perf-report b/scripts/oe-build-perf-report
index 8d730cd20a..0b2f730e57 100755
--- a/scripts/oe-build-perf-report
+++ b/scripts/oe-build-perf-report
@@ -32,6 +32,7 @@ from build_perf.report import (metadata_xml_to_json, results_xml_to_json,
32 aggregate_data, aggregate_metadata, measurement_stats, 32 aggregate_data, aggregate_metadata, measurement_stats,
33 AggregateTestData) 33 AggregateTestData)
34from build_perf import html 34from build_perf import html
35from buildstats import BuildStats, diff_buildstats
35 36
36scriptpath.add_oe_lib_path() 37scriptpath.add_oe_lib_path()
37 38
@@ -333,12 +334,31 @@ def print_diff_report(metadata_l, data_l, metadata_r, data_r):
333 print() 334 print()
334 335
335 336
336def print_html_report(data, id_comp): 337class BSSummary(object):
338 def __init__(self, bs1, bs2):
339 self.tasks = {'count': bs2.num_tasks,
340 'change': '{:+d}'.format(bs2.num_tasks - bs1.num_tasks)}
341 self.top_consumer = None
342 self.top_decrease = None
343 self.top_increase = None
344
345 tasks_diff = diff_buildstats(bs1, bs2, 'cputime')
346
347 # Get top consumers of resources
348 tasks_diff = sorted(tasks_diff, key=attrgetter('value2'))
349 self.top_consumer = tasks_diff[-5:]
350
351 # Get biggest increase and decrease in resource usage
352 tasks_diff = sorted(tasks_diff, key=attrgetter('absdiff'))
353 self.top_decrease = tasks_diff[0:5]
354 self.top_increase = tasks_diff[-5:]
355
356
357def print_html_report(data, id_comp, buildstats):
337 """Print report in html format""" 358 """Print report in html format"""
338 # Handle metadata 359 # Handle metadata
339 metadata = metadata_diff(data[id_comp].metadata, data[-1].metadata) 360 metadata = metadata_diff(data[id_comp].metadata, data[-1].metadata)
340 361
341
342 # Generate list of tests 362 # Generate list of tests
343 tests = [] 363 tests = []
344 for test in data[-1].results['tests'].keys(): 364 for test in data[-1].results['tests'].keys():
@@ -388,6 +408,16 @@ def print_html_report(data, id_comp):
388 new_meas['value'] = samples[-1] 408 new_meas['value'] = samples[-1]
389 new_meas['value_type'] = samples[-1]['val_cls'] 409 new_meas['value_type'] = samples[-1]['val_cls']
390 410
411 # Compare buildstats
412 bs_key = test + '.' + meas
413 rev = metadata['commit_num']['value']
414 comp_rev = metadata['commit_num']['value_old']
415 if (rev in buildstats and bs_key in buildstats[rev] and
416 comp_rev in buildstats and bs_key in buildstats[comp_rev]):
417 new_meas['buildstats'] = BSSummary(buildstats[comp_rev][bs_key],
418 buildstats[rev][bs_key])
419
420
391 new_test['measurements'].append(new_meas) 421 new_test['measurements'].append(new_meas)
392 tests.append(new_test) 422 tests.append(new_test)
393 423
@@ -401,8 +431,8 @@ def print_html_report(data, id_comp):
401 chart_opts=chart_opts)) 431 chart_opts=chart_opts))
402 432
403 433
404def dump_buildstats(repo, outdir, notes_ref, revs): 434def get_buildstats(repo, notes_ref, revs, outdir=None):
405 """Dump buildstats of test results""" 435 """Get the buildstats from git notes"""
406 full_ref = 'refs/notes/' + notes_ref 436 full_ref = 'refs/notes/' + notes_ref
407 if not repo.rev_parse(full_ref): 437 if not repo.rev_parse(full_ref):
408 log.error("No buildstats found, please try running " 438 log.error("No buildstats found, please try running "
@@ -411,9 +441,10 @@ def dump_buildstats(repo, outdir, notes_ref, revs):
411 return 441 return
412 442
413 missing = False 443 missing = False
414 log.info("Writing out buildstats from 'refs/notes/%s' into '%s'", 444 buildstats = {}
415 notes_ref, outdir) 445 log.info("Parsing buildstats from 'refs/notes/%s'", notes_ref)
416 for rev in revs: 446 for rev in revs:
447 buildstats[rev.commit_number] = {}
417 log.debug('Dumping buildstats for %s (%s)', rev.commit_number, 448 log.debug('Dumping buildstats for %s (%s)', rev.commit_number,
418 rev.commit) 449 rev.commit)
419 for tag in rev.tags: 450 for tag in rev.tags:
@@ -425,19 +456,32 @@ def dump_buildstats(repo, outdir, notes_ref, revs):
425 log.warning("Buildstats not found for %s", tag) 456 log.warning("Buildstats not found for %s", tag)
426 bs_all = {} 457 bs_all = {}
427 missing = True 458 missing = True
428 for measurement, buildstats in bs_all.items(): 459
429 tag_base, run_id = tag.rsplit('/', 1) 460 for measurement, bs in bs_all.items():
430 tag_base = tag_base.replace('/', '_') 461 # Write out onto disk
431 bs_dir = os.path.join(outdir, measurement, tag_base) 462 if outdir:
432 if not os.path.exists(bs_dir): 463 tag_base, run_id = tag.rsplit('/', 1)
433 os.makedirs(bs_dir) 464 tag_base = tag_base.replace('/', '_')
434 with open(os.path.join(bs_dir, run_id + '.json'), 'w') as f: 465 bs_dir = os.path.join(outdir, measurement, tag_base)
435 json.dump(buildstats, f, indent=2) 466 if not os.path.exists(bs_dir):
467 os.makedirs(bs_dir)
468 with open(os.path.join(bs_dir, run_id + '.json'), 'w') as f:
469 json.dump(bs, f, indent=2)
470
471 # Read buildstats into a dict
472 _bs = BuildStats.from_json(bs)
473 if measurement not in buildstats[rev.commit_number]:
474 buildstats[rev.commit_number][measurement] = _bs
475 else:
476 buildstats[rev.commit_number][measurement].aggregate(_bs)
477
436 if missing: 478 if missing:
437 log.info("Buildstats were missing for some test runs, please " 479 log.info("Buildstats were missing for some test runs, please "
438 "run 'git fetch origin %s:%s' and try again", 480 "run 'git fetch origin %s:%s' and try again",
439 full_ref, full_ref) 481 full_ref, full_ref)
440 482
483 return buildstats
484
441 485
442def auto_args(repo, args): 486def auto_args(repo, args):
443 """Guess arguments, if not defined by the user""" 487 """Guess arguments, if not defined by the user"""
@@ -584,20 +628,20 @@ def main(argv=None):
584 index_r = index_r - index_0 628 index_r = index_r - index_0
585 index_l = index_l - index_0 629 index_l = index_l - index_0
586 630
631 # Read buildstats only when needed
632 buildstats = None
633 if args.dump_buildstats or args.html:
634 outdir = 'oe-build-perf-buildstats' if args.dump_buildstats else None
635 notes_ref = 'buildstats/{}/{}/{}'.format(args.hostname, args.branch,
636 args.machine)
637 buildstats = get_buildstats(repo, notes_ref, [rev_l, rev_r], outdir)
638
587 # Print report 639 # Print report
588 if not args.html: 640 if not args.html:
589 print_diff_report(data[index_l].metadata, data[index_l].results, 641 print_diff_report(data[index_l].metadata, data[index_l].results,
590 data[index_r].metadata, data[index_r].results) 642 data[index_r].metadata, data[index_r].results)
591 else: 643 else:
592 print_html_report(data, index_l) 644 print_html_report(data, index_l, buildstats)
593
594 # Dump buildstats
595 if args.dump_buildstats:
596 notes_ref = 'buildstats/{}/{}/{}'.format(args.hostname, args.branch,
597 args.machine)
598 dump_buildstats(repo, 'oe-build-perf-buildstats', notes_ref,
599 [rev_l, rev_r])
600 #revs_l.tags + revs_r.tags)
601 645
602 return 0 646 return 0
603 647