488 write_to_chrome(data, fp, **kwargs) |
488 write_to_chrome(data, fp, **kwargs) |
489 else: |
489 else: |
490 raise Exception("Invalid display format") |
490 raise Exception("Invalid display format") |
491 |
491 |
492 if format not in (DisplayFormats.Json, DisplayFormats.Chrome): |
492 if format not in (DisplayFormats.Json, DisplayFormats.Chrome): |
493 print('---', file=fp) |
493 fp.write(b'---\n') |
494 print('Sample count: %d' % len(data.samples), file=fp) |
494 fp.write(b'Sample count: %d\n' % len(data.samples)) |
495 print('Total time: %f seconds (%f wall)' % data.accumulated_time, |
495 fp.write(b'Total time: %f seconds (%f wall)\n' % data.accumulated_time) |
496 file=fp) |
|
497 |
496 |
498 def display_by_line(data, fp): |
497 def display_by_line(data, fp): |
499 '''Print the profiler data with each sample line represented |
498 '''Print the profiler data with each sample line represented |
500 as one row in a table. Sorted by self-time per line.''' |
499 as one row in a table. Sorted by self-time per line.''' |
501 stats = SiteStats.buildstats(data.samples) |
500 stats = SiteStats.buildstats(data.samples) |
502 stats.sort(reverse=True, key=lambda x: x.selfseconds()) |
501 stats.sort(reverse=True, key=lambda x: x.selfseconds()) |
503 |
502 |
504 print('%5.5s %10.10s %7.7s %-8.8s' % |
503 fp.write(b'%5.5s %10.10s %7.7s %-8.8s\n' % ( |
505 ('% ', 'cumulative', 'self', ''), file=fp) |
504 b'% ', b'cumulative', b'self', b'')) |
506 print('%5.5s %9.9s %8.8s %-8.8s' % |
505 fp.write(b'%5.5s %9.9s %8.8s %-8.8s\n' % ( |
507 ("time", "seconds", "seconds", "name"), file=fp) |
506 b"time", b"seconds", b"seconds", b"name")) |
508 |
507 |
509 for stat in stats: |
508 for stat in stats: |
510 site = stat.site |
509 site = stat.site |
511 sitelabel = '%s:%d:%s' % (site.filename(), site.lineno, site.function) |
510 sitelabel = '%s:%d:%s' % (site.filename(), site.lineno, site.function) |
512 print('%6.2f %9.2f %9.2f %s' % (stat.selfpercent(), |
511 fp.write(b'%6.2f %9.2f %9.2f %s\n' % ( |
513 stat.totalseconds(), |
512 stat.selfpercent(), stat.totalseconds(), |
514 stat.selfseconds(), |
513 stat.selfseconds(), sitelabel)) |
515 sitelabel), |
|
516 file=fp) |
|
517 |
514 |
518 def display_by_method(data, fp): |
515 def display_by_method(data, fp): |
519 '''Print the profiler data with each sample function represented |
516 '''Print the profiler data with each sample function represented |
520 as one row in a table. Important lines within that function are |
517 as one row in a table. Important lines within that function are |
521 output as nested rows. Sorted by self-time per line.''' |
518 output as nested rows. Sorted by self-time per line.''' |
522 print('%5.5s %10.10s %7.7s %-8.8s' % |
519 fp.write(b'%5.5s %10.10s %7.7s %-8.8s\n' % |
523 ('% ', 'cumulative', 'self', ''), file=fp) |
520 ('% ', 'cumulative', 'self', '')) |
524 print('%5.5s %9.9s %8.8s %-8.8s' % |
521 fp.write(b'%5.5s %9.9s %8.8s %-8.8s\n' % |
525 ("time", "seconds", "seconds", "name"), file=fp) |
522 ("time", "seconds", "seconds", "name")) |
526 |
523 |
527 stats = SiteStats.buildstats(data.samples) |
524 stats = SiteStats.buildstats(data.samples) |
528 |
525 |
529 grouped = defaultdict(list) |
526 grouped = defaultdict(list) |
530 for stat in stats: |
527 for stat in stats: |
551 functiondata.sort(reverse=True, key=lambda x: x[2]) |
548 functiondata.sort(reverse=True, key=lambda x: x[2]) |
552 |
549 |
553 for function in functiondata: |
550 for function in functiondata: |
554 if function[3] < 0.05: |
551 if function[3] < 0.05: |
555 continue |
552 continue |
556 print('%6.2f %9.2f %9.2f %s' % (function[3], # total percent |
553 fp.write(b'%6.2f %9.2f %9.2f %s\n' % ( |
557 function[1], # total cum sec |
554 function[3], # total percent |
558 function[2], # total self sec |
555 function[1], # total cum sec |
559 function[0]), # file:function |
556 function[2], # total self sec |
560 file=fp) |
557 function[0])) # file:function |
|
558 |
561 function[4].sort(reverse=True, key=lambda i: i.selfseconds()) |
559 function[4].sort(reverse=True, key=lambda i: i.selfseconds()) |
562 for stat in function[4]: |
560 for stat in function[4]: |
563 # only show line numbers for significant locations (>1% time spent) |
561 # only show line numbers for significant locations (>1% time spent) |
564 if stat.selfpercent() > 1: |
562 if stat.selfpercent() > 1: |
565 source = stat.site.getsource(25) |
563 source = stat.site.getsource(25) |
566 stattuple = (stat.selfpercent(), stat.selfseconds(), |
564 stattuple = (stat.selfpercent(), stat.selfseconds(), |
567 stat.site.lineno, source) |
565 stat.site.lineno, source) |
568 |
566 |
569 print('%33.0f%% %6.2f line %d: %s' % (stattuple), file=fp) |
567 fp.write(b'%33.0f%% %6.2f line %d: %s\n' % stattuple) |
570 |
568 |
571 def display_about_method(data, fp, function=None, **kwargs): |
569 def display_about_method(data, fp, function=None, **kwargs): |
572 if function is None: |
570 if function is None: |
573 raise Exception("Invalid function") |
571 raise Exception("Invalid function") |
574 |
572 |
598 children[site] = 1 |
596 children[site] = 1 |
599 |
597 |
600 parents = [(parent, count) for parent, count in parents.iteritems()] |
598 parents = [(parent, count) for parent, count in parents.iteritems()] |
601 parents.sort(reverse=True, key=lambda x: x[1]) |
599 parents.sort(reverse=True, key=lambda x: x[1]) |
602 for parent, count in parents: |
600 for parent, count in parents: |
603 print('%6.2f%% %s:%s line %s: %s' % |
601 fp.write(b'%6.2f%% %s:%s line %s: %s\n' % |
604 (count / relevant_samples * 100, parent.filename(), |
602 (count / relevant_samples * 100, parent.filename(), |
605 parent.function, parent.lineno, parent.getsource(50)), file=fp) |
603 parent.function, parent.lineno, parent.getsource(50))) |
606 |
604 |
607 stats = SiteStats.buildstats(data.samples) |
605 stats = SiteStats.buildstats(data.samples) |
608 stats = [s for s in stats |
606 stats = [s for s in stats |
609 if s.site.function == function and |
607 if s.site.function == function and |
610 (not filename or s.site.filename() == filename)] |
608 (not filename or s.site.filename() == filename)] |
617 total_cum_sec += stat.totalseconds() |
615 total_cum_sec += stat.totalseconds() |
618 total_self_sec += stat.selfseconds() |
616 total_self_sec += stat.selfseconds() |
619 total_self_percent += stat.selfpercent() |
617 total_self_percent += stat.selfpercent() |
620 total_cum_percent += stat.totalpercent() |
618 total_cum_percent += stat.totalpercent() |
621 |
619 |
622 print( |
620 fp.write( |
623 '\n %s:%s Total: %0.2fs (%0.2f%%) Self: %0.2fs (%0.2f%%)\n' % |
621 b'\n %s:%s Total: %0.2fs (%0.2f%%) Self: %0.2fs (%0.2f%%)\n\n' |
624 ( |
622 % ( |
625 filename or '___', |
623 filename or '___', |
626 function, |
624 function, |
627 total_cum_sec, |
625 total_cum_sec, |
628 total_cum_percent, |
626 total_cum_percent, |
629 total_self_sec, |
627 total_self_sec, |
630 total_self_percent |
628 total_self_percent |
631 ), file=fp) |
629 )) |
632 |
630 |
633 children = [(child, count) for child, count in children.iteritems()] |
631 children = [(child, count) for child, count in children.iteritems()] |
634 children.sort(reverse=True, key=lambda x: x[1]) |
632 children.sort(reverse=True, key=lambda x: x[1]) |
635 for child, count in children: |
633 for child, count in children: |
636 print(' %6.2f%% line %s: %s' % |
634 fp.write(b' %6.2f%% line %s: %s\n' % |
637 (count / relevant_samples * 100, child.lineno, |
635 (count / relevant_samples * 100, child.lineno, |
638 child.getsource(50)), file=fp) |
636 child.getsource(50))) |
639 |
637 |
640 def display_hotpath(data, fp, limit=0.05, **kwargs): |
638 def display_hotpath(data, fp, limit=0.05, **kwargs): |
641 class HotNode(object): |
639 class HotNode(object): |
642 def __init__(self, site): |
640 def __init__(self, site): |
643 self.site = site |
641 self.site = site |
712 |
710 |
713 def write_to_flame(data, fp, scriptpath=None, outputfile=None, **kwargs): |
711 def write_to_flame(data, fp, scriptpath=None, outputfile=None, **kwargs): |
714 if scriptpath is None: |
712 if scriptpath is None: |
715 scriptpath = encoding.environ['HOME'] + '/flamegraph.pl' |
713 scriptpath = encoding.environ['HOME'] + '/flamegraph.pl' |
716 if not os.path.exists(scriptpath): |
714 if not os.path.exists(scriptpath): |
717 print("error: missing %s" % scriptpath, file=fp) |
715 fp.write(b'error: missing %s\n' % scriptpath) |
718 print("get it here: https://github.com/brendangregg/FlameGraph", |
716 fp.write(b'get it here: https://github.com/brendangregg/FlameGraph\n') |
719 file=fp) |
|
720 return |
717 return |
721 |
718 |
722 fd, path = pycompat.mkstemp() |
719 fd, path = pycompat.mkstemp() |
723 |
720 |
724 file = open(path, "w+") |
721 file = open(path, "w+") |