# HG changeset patch # User Bryan O'Sullivan # Date 1201900185 28800 # Node ID b913d3aacddcec52732381839a0987719c39d217 # Parent a445388aa554b657f1eb448953ac04dc07b2bb74 profiling: allow CGI and FastCGI to be profiled diff -r a445388aa554 -r b913d3aacddc contrib/hgwebdir.fcgi --- a/contrib/hgwebdir.fcgi Fri Feb 01 10:31:15 2008 +0100 +++ b/contrib/hgwebdir.fcgi Fri Feb 01 13:09:45 2008 -0800 @@ -23,6 +23,7 @@ from mercurial.hgweb.hgwebdir_mod import hgwebdir from mercurial.hgweb.request import wsgiapplication +from mercurial import dispatch, ui from flup.server.fcgi import WSGIServer # The config file looks like this. You can have paths to individual @@ -44,7 +45,8 @@ # Alternatively you can pass a list of ('virtual/path', '/real/path') tuples # or use a dictionary with entries like 'virtual/path': '/real/path' -def make_web_app(): - return hgwebdir("hgweb.config") +def web_app(ui): + return lambda: hgwebdir("hgweb.config", ui) -WSGIServer(wsgiapplication(make_web_app)).run() +u = ui.ui(report_untrusted=False, interactive=False) +dispatch.profiled(u, lambda: WSGIServer(wsgiapplication(web_app(u))).run()) diff -r a445388aa554 -r b913d3aacddc doc/hgrc.5.txt --- a/doc/hgrc.5.txt Fri Feb 01 10:31:15 2008 +0100 +++ b/doc/hgrc.5.txt Fri Feb 01 13:09:45 2008 -0800 @@ -403,6 +403,17 @@ Optional. Directory or URL to use when pushing if no destination is specified. +profile:: + Configuration of profiling options, for in-depth performance + analysis. Mostly useful to developers. + enable;; + Enable a particular profiling mode. Useful for profiling + server-side processes. "lsprof" enables modern profiling. + "hotshot" is deprecated, and produces less reliable results. + Default is no profiling. + output;; + The name of a file to write profiling data to. Default is stderr. + server:: Controls generic server settings. uncompressed;; diff -r a445388aa554 -r b913d3aacddc hgweb.cgi --- a/hgweb.cgi Fri Feb 01 10:31:15 2008 +0100 +++ b/hgweb.cgi Fri Feb 01 13:09:45 2008 -0800 @@ -22,7 +22,9 @@ #os.environ["HGENCODING"] = "UTF-8" from mercurial.hgweb.hgweb_mod import hgweb +from mercurial import dispatch, ui import mercurial.hgweb.wsgicgi as wsgicgi -application = hgweb("/path/to/repo", "repository name") -wsgicgi.launch(application) +u = ui.ui(report_untrusted=False, interactive=False) +dispatch.profiled(u, lambda: wsgicgi.launch(hgweb("/path/to/repo", + "repository name", u))) diff -r a445388aa554 -r b913d3aacddc hgwebdir.cgi --- a/hgwebdir.cgi Fri Feb 01 10:31:15 2008 +0100 +++ b/hgwebdir.cgi Fri Feb 01 13:09:45 2008 -0800 @@ -22,6 +22,7 @@ #os.environ["HGENCODING"] = "UTF-8" from mercurial.hgweb.hgwebdir_mod import hgwebdir +from mercurial import dispatch, ui import mercurial.hgweb.wsgicgi as wsgicgi # The config file looks like this. You can have paths to individual @@ -43,5 +44,5 @@ # Alternatively you can pass a list of ('virtual/path', '/real/path') tuples # or use a dictionary with entries like 'virtual/path': '/real/path' -application = hgwebdir('hgweb.config') -wsgicgi.launch(application) +u = ui.ui(report_untrusted=False, interactive=False) +dispatch.profiled(u, lambda: wsgicgi.launch(hgwebdir('hgweb.config', u))) diff -r a445388aa554 -r b913d3aacddc mercurial/dispatch.py --- a/mercurial/dispatch.py Fri Feb 01 10:31:15 2008 +0100 +++ b/mercurial/dispatch.py Fri Feb 01 13:09:45 2008 -0800 @@ -373,8 +373,17 @@ if len(tb) != 2: # no raise raise ParseError(cmd, _("invalid arguments")) + return profiled(ui, checkargs, options) - if options['profile']: +def profiled(ui, func, options={}): + def profile_fp(): + outfile = ui.config('profile', 'output', untrusted=True) + if outfile: + return open(outfile, 'w') + else: + return sys.stderr + + if options.get('profile') or ui.config('profile', 'enable') == 'hotshot': import hotshot, hotshot.stats prof = hotshot.Profile("hg.prof") try: @@ -390,10 +399,11 @@ finally: prof.close() stats = hotshot.stats.load("hg.prof") + stats.stream = profile_fp() stats.strip_dirs() stats.sort_stats('time', 'calls') stats.print_stats(40) - elif options['lsprof']: + elif options.get('lsprof') or ui.config('profile', 'enable') == 'lsprof': try: from mercurial import lsprof except ImportError: @@ -403,11 +413,11 @@ p = lsprof.Profiler() p.enable(subcalls=True) try: - return checkargs() + return func() finally: p.disable() stats = lsprof.Stats(p.getstats()) stats.sort() - stats.pprint(top=10, file=sys.stderr, climit=5) + stats.pprint(top=10, file=profile_fp(), climit=5) else: - return checkargs() + return func() diff -r a445388aa554 -r b913d3aacddc mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py Fri Feb 01 10:31:15 2008 +0100 +++ b/mercurial/hgweb/hgweb_mod.py Fri Feb 01 13:09:45 2008 -0800 @@ -79,9 +79,10 @@ return nav class hgweb(object): - def __init__(self, repo, name=None): + def __init__(self, repo, name=None, parentui=None): if isinstance(repo, str): - parentui = ui.ui(report_untrusted=False, interactive=False) + parentui = (parentui or + ui.ui(report_untrusted=False, interactive=False)) self.repo = hg.repository(parentui, repo) else: self.repo = repo