comparison mercurial/dispatch.py @ 16392:ee3f423df1b4

dispatch: add support for statprof as a profiler This can be selected using the config variable profiling.type or the environment variable HGPROF ("ls" for the default, "stat" for statprof). The only tuneable is the frequency, profiling.freq, which defaults to 1000 Hz. If statprof is not available, a warning is printed.
author Bryan O'Sullivan <bryano@fb.com>
date Mon, 09 Apr 2012 13:48:45 -0700
parents ba42eb722bb3
children 46e9ed223d2c
comparison
equal deleted inserted replaced
16391:9cf7c9d529d0 16392:ee3f423df1b4
685 cmdpats, cmdoptions) 685 cmdpats, cmdoptions)
686 finally: 686 finally:
687 if repo and repo != req.repo: 687 if repo and repo != req.repo:
688 repo.close() 688 repo.close()
689 689
690 def lsprofile(ui, func, fp):
691 format = ui.config('profiling', 'format', default='text')
692 field = ui.config('profiling', 'sort', default='inlinetime')
693 climit = ui.configint('profiling', 'nested', default=5)
694
695 if not format in ['text', 'kcachegrind']:
696 ui.warn(_("unrecognized profiling format '%s'"
697 " - Ignored\n") % format)
698 format = 'text'
699
700 try:
701 from mercurial import lsprof
702 except ImportError:
703 raise util.Abort(_(
704 'lsprof not available - install from '
705 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
706 p = lsprof.Profiler()
707 p.enable(subcalls=True)
708 try:
709 return func()
710 finally:
711 p.disable()
712
713 if format == 'kcachegrind':
714 import lsprofcalltree
715 calltree = lsprofcalltree.KCacheGrind(p)
716 calltree.output(fp)
717 else:
718 # format == 'text'
719 stats = lsprof.Stats(p.getstats())
720 stats.sort(field)
721 stats.pprint(limit=30, file=fp, climit=climit)
722
723 def statprofile(ui, func, fp):
724 try:
725 import statprof
726 except ImportError:
727 raise util.Abort(_(
728 'statprof not available - install using "easy_install statprof"'))
729
730 freq = ui.configint('profiling', 'freq', default=1000)
731 if freq > 0:
732 statprof.reset(freq)
733 else:
734 ui.warn(_("invalid sampling frequency '%s' - ignoring\n") % freq)
735
736 statprof.start()
737 try:
738 return func()
739 finally:
740 statprof.stop()
741 statprof.display(fp)
742
690 def _runcommand(ui, options, cmd, cmdfunc): 743 def _runcommand(ui, options, cmd, cmdfunc):
691 def checkargs(): 744 def checkargs():
692 try: 745 try:
693 return cmdfunc() 746 return cmdfunc()
694 except error.SignatureError: 747 except error.SignatureError:
695 raise error.CommandError(cmd, _("invalid arguments")) 748 raise error.CommandError(cmd, _("invalid arguments"))
696 749
697 if options['profile']: 750 if options['profile']:
698 format = ui.config('profiling', 'format', default='text') 751 profiler = os.getenv('HGPROF')
699 field = ui.config('profiling', 'sort', default='inlinetime') 752 if profiler is None:
700 climit = ui.configint('profiling', 'nested', default=5) 753 profiler = ui.config('profiling', 'type', default='ls')
701 754 if profiler not in ('ls', 'stat'):
702 if not format in ['text', 'kcachegrind']: 755 ui.warn(_("unrecognized profiler '%s' - ignored\n") % profiler)
703 ui.warn(_("unrecognized profiling format '%s'" 756 profiler = 'ls'
704 " - Ignored\n") % format)
705 format = 'text'
706 757
707 output = ui.config('profiling', 'output') 758 output = ui.config('profiling', 'output')
708 759
709 if output: 760 if output:
710 path = ui.expandpath(output) 761 path = ui.expandpath(output)
711 ostream = open(path, 'wb') 762 fp = open(path, 'wb')
712 else: 763 else:
713 ostream = sys.stderr 764 fp = sys.stderr
714 765
715 try: 766 try:
716 from mercurial import lsprof 767 if profiler == 'ls':
717 except ImportError: 768 return lsprofile(ui, checkargs, fp)
718 raise util.Abort(_( 769 else:
719 'lsprof not available - install from ' 770 return statprofile(ui, checkargs, fp)
720 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
721 p = lsprof.Profiler()
722 p.enable(subcalls=True)
723 try:
724 return checkargs()
725 finally: 771 finally:
726 p.disable()
727
728 if format == 'kcachegrind':
729 import lsprofcalltree
730 calltree = lsprofcalltree.KCacheGrind(p)
731 calltree.output(ostream)
732 else:
733 # format == 'text'
734 stats = lsprof.Stats(p.getstats())
735 stats.sort(field)
736 stats.pprint(limit=30, file=ostream, climit=climit)
737
738 if output: 772 if output:
739 ostream.close() 773 fp.close()
740 else: 774 else:
741 return checkargs() 775 return checkargs()