##// END OF EJS Templates
hgweb: profile HTTP requests...
hgweb: profile HTTP requests Currently, running `hg serve --profile` doesn't yield anything useful: when the process is terminated the profiling output displays results from the main thread, which typically spends most of its time in select.select(). Furthermore, it has no meaningful results from mercurial.* modules because the threads serving HTTP requests don't actually get profiled. This patch teaches the hgweb wsgi applications to profile individual requests. If profiling is enabled, the profiler kicks in after HTTP/WSGI environment processing but before Mercurial's main request processing. The profile results are printed to the configured profiling output. If running `hg serve` from a shell, they will be printed to stderr, just before the HTTP request line is logged. If profiling to a file, we only write a single profile to the file because the file is not opened in append mode. We could add support for appending to files in a future patch if someone wants it. Per request profiling doesn't work with the statprof profiler because internally that profiler collects samples from the thread that *initially* requested profiling be enabled. I have plans to address this by vendoring Facebook's customized statprof and then improving it.

File last commit:

r28027:14033c5d default
r29787:80df0426 default
Show More
test-lock.py
271 lines | 8.6 KiB | text/x-python | PythonLexer
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 from __future__ import absolute_import
Siddharth Agarwal
test-lock.py: fix testing for forks...
r26386 import copy
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 import os
import silenttestrunner
import tempfile
Siddharth Agarwal
test-lock.py: fix testing for forks...
r26386 import types
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 import unittest
from mercurial import (
Siddharth Agarwal
lock: add a way to prevent locks from being inherited...
r26498 error,
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock,
scmutil,
)
testlockname = 'testlock'
Siddharth Agarwal
test-lock.py: fix testing for forks...
r26386 # work around http://bugs.python.org/issue1515
if types.MethodType not in copy._deepcopy_dispatch:
def _deepcopy_method(x, memo):
return type(x)(x.im_func, copy.deepcopy(x.im_self, memo), x.im_class)
copy._deepcopy_dispatch[types.MethodType] = _deepcopy_method
Siddharth Agarwal
test-lock.py: add a lock wrapper that allows faking the PID...
r26384 class lockwrapper(lock.lock):
def __init__(self, pidoffset, *args, **kwargs):
# lock.lock.__init__() calls lock(), so the pidoffset assignment needs
# to be earlier
self._pidoffset = pidoffset
super(lockwrapper, self).__init__(*args, **kwargs)
def _getpid(self):
timeless
util: enable getpid to be replaced...
r28027 return super(lockwrapper, self)._getpid() + self._pidoffset
Siddharth Agarwal
test-lock.py: add a lock wrapper that allows faking the PID...
r26384
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 class teststate(object):
Siddharth Agarwal
test-lock.py: allow PID to be changed in test state...
r26385 def __init__(self, testcase, dir, pidoffset=0):
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 self._testcase = testcase
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 self._acquirecalled = False
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 self._releasecalled = False
self._postreleasecalled = False
Siddharth Agarwal
test-lock.py: move temp dir generation to testcase...
r26382 self.vfs = scmutil.vfs(dir, audit=False)
Siddharth Agarwal
test-lock.py: allow PID to be changed in test state...
r26385 self._pidoffset = pidoffset
Siddharth Agarwal
tests: add unit tests for locking code...
r26289
def makelock(self, *args, **kwargs):
Siddharth Agarwal
test-lock.py: allow PID to be changed in test state...
r26385 l = lockwrapper(self._pidoffset, self.vfs, testlockname,
releasefn=self.releasefn, acquirefn=self.acquirefn,
*args, **kwargs)
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 l.postrelease.append(self.postreleasefn)
return l
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 def acquirefn(self):
self._acquirecalled = True
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 def releasefn(self):
self._releasecalled = True
def postreleasefn(self):
self._postreleasecalled = True
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 def assertacquirecalled(self, called):
self._testcase.assertEqual(
self._acquirecalled, called,
'expected acquire to be %s but was actually %s' % (
self._tocalled(called),
self._tocalled(self._acquirecalled),
))
def resetacquirefn(self):
self._acquirecalled = False
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 def assertreleasecalled(self, called):
self._testcase.assertEqual(
self._releasecalled, called,
'expected release to be %s but was actually %s' % (
self._tocalled(called),
self._tocalled(self._releasecalled),
))
def assertpostreleasecalled(self, called):
self._testcase.assertEqual(
self._postreleasecalled, called,
'expected postrelease to be %s but was actually %s' % (
self._tocalled(called),
self._tocalled(self._postreleasecalled),
))
def assertlockexists(self, exists):
actual = self.vfs.lexists(testlockname)
self._testcase.assertEqual(
actual, exists,
'expected lock to %s but actually did %s' % (
self._toexists(exists),
self._toexists(actual),
))
def _tocalled(self, called):
if called:
return 'called'
else:
return 'not called'
def _toexists(self, exists):
if exists:
Siddharth Agarwal
test-lock.py: copy-edit assertions about file existing...
r26381 return 'exist'
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 else:
Siddharth Agarwal
test-lock.py: copy-edit assertions about file existing...
r26381 return 'not exist'
Siddharth Agarwal
tests: add unit tests for locking code...
r26289
class testlock(unittest.TestCase):
def testlock(self):
Siddharth Agarwal
test-lock.py: move temp dir generation to testcase...
r26382 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock = state.makelock()
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 state.assertacquirecalled(True)
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock.release()
state.assertreleasecalled(True)
state.assertpostreleasecalled(True)
state.assertlockexists(False)
def testrecursivelock(self):
Siddharth Agarwal
test-lock.py: move temp dir generation to testcase...
r26382 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock = state.makelock()
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 state.assertacquirecalled(True)
state.resetacquirefn()
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock.lock()
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 # recursive lock should not call acquirefn again
state.assertacquirecalled(False)
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock.release() # brings lock refcount down from 2 to 1
state.assertreleasecalled(False)
state.assertpostreleasecalled(False)
state.assertlockexists(True)
lock.release() # releases the lock
state.assertreleasecalled(True)
state.assertpostreleasecalled(True)
state.assertlockexists(False)
def testlockfork(self):
Siddharth Agarwal
test-lock.py: move temp dir generation to testcase...
r26382 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock = state.makelock()
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 state.assertacquirecalled(True)
Siddharth Agarwal
test-lock.py: fix testing for forks...
r26386
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 # fake a fork
Siddharth Agarwal
test-lock.py: fix testing for forks...
r26386 forklock = copy.deepcopy(lock)
forklock._pidoffset = 1
forklock.release()
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 state.assertreleasecalled(False)
state.assertpostreleasecalled(False)
state.assertlockexists(True)
# release the actual lock
lock.release()
state.assertreleasecalled(True)
state.assertpostreleasecalled(True)
state.assertlockexists(False)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387 def testinheritlock(self):
d = tempfile.mkdtemp(dir=os.getcwd())
parentstate = teststate(self, d)
parentlock = parentstate.makelock()
parentstate.assertacquirecalled(True)
# set up lock inheritance
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 with parentlock.inherit() as lockname:
parentstate.assertreleasecalled(True)
parentstate.assertpostreleasecalled(False)
parentstate.assertlockexists(True)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 childstate = teststate(self, d, pidoffset=1)
childlock = childstate.makelock(parentlock=lockname)
childstate.assertacquirecalled(True)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 childlock.release()
childstate.assertreleasecalled(True)
Siddharth Agarwal
lock.release: don't call postrelease functions for inherited locks...
r26474 childstate.assertpostreleasecalled(False)
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 childstate.assertlockexists(True)
parentstate.resetacquirefn()
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387 parentstate.assertacquirecalled(True)
parentlock.release()
parentstate.assertreleasecalled(True)
parentstate.assertpostreleasecalled(True)
parentstate.assertlockexists(False)
def testmultilock(self):
d = tempfile.mkdtemp(dir=os.getcwd())
state0 = teststate(self, d)
lock0 = state0.makelock()
state0.assertacquirecalled(True)
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 with lock0.inherit() as lock0name:
state0.assertreleasecalled(True)
state0.assertpostreleasecalled(False)
state0.assertlockexists(True)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 state1 = teststate(self, d, pidoffset=1)
lock1 = state1.makelock(parentlock=lock0name)
state1.assertacquirecalled(True)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 # from within lock1, acquire another lock
with lock1.inherit() as lock1name:
# since the file on disk is lock0's this should have the same
# name
self.assertEqual(lock0name, lock1name)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 state2 = teststate(self, d, pidoffset=2)
lock2 = state2.makelock(parentlock=lock1name)
state2.assertacquirecalled(True)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 lock2.release()
state2.assertreleasecalled(True)
Siddharth Agarwal
lock.release: don't call postrelease functions for inherited locks...
r26474 state2.assertpostreleasecalled(False)
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 state2.assertlockexists(True)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 state1.resetacquirefn()
state1.assertacquirecalled(True)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 lock1.release()
state1.assertreleasecalled(True)
Siddharth Agarwal
lock.release: don't call postrelease functions for inherited locks...
r26474 state1.assertpostreleasecalled(False)
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 state1.assertlockexists(True)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387
lock0.release()
def testinheritlockfork(self):
d = tempfile.mkdtemp(dir=os.getcwd())
parentstate = teststate(self, d)
parentlock = parentstate.makelock()
parentstate.assertacquirecalled(True)
# set up lock inheritance
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 with parentlock.inherit() as lockname:
childstate = teststate(self, d, pidoffset=1)
childlock = childstate.makelock(parentlock=lockname)
childstate.assertacquirecalled(True)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 # fork the child lock
forkchildlock = copy.deepcopy(childlock)
forkchildlock._pidoffset += 1
forkchildlock.release()
childstate.assertreleasecalled(False)
childstate.assertpostreleasecalled(False)
childstate.assertlockexists(True)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 # release the child lock
childlock.release()
childstate.assertreleasecalled(True)
Siddharth Agarwal
lock.release: don't call postrelease functions for inherited locks...
r26474 childstate.assertpostreleasecalled(False)
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 childstate.assertlockexists(True)
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387
parentlock.release()
Siddharth Agarwal
lock: add a way to prevent locks from being inherited...
r26498 def testinheritcheck(self):
d = tempfile.mkdtemp(dir=os.getcwd())
state = teststate(self, d)
def check():
raise error.LockInheritanceContractViolation('check failed')
lock = state.makelock(inheritchecker=check)
state.assertacquirecalled(True)
def tryinherit():
Siddharth Agarwal
localrepo: prevent wlock from being inherited when a transaction is running...
r26499 with lock.inherit():
Siddharth Agarwal
lock: add a way to prevent locks from being inherited...
r26498 pass
self.assertRaises(error.LockInheritanceContractViolation, tryinherit)
lock.release()
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 if __name__ == '__main__':
silenttestrunner.main(__name__)