With this patch, this command works:
python3 hg --profile --config profiling.statformat=chrome st
(and it works with s/python3/python2/ as well)
pulkit |
hg-reviewers |
With this patch, this command works:
python3 hg --profile --config profiling.statformat=chrome st
(and it works with s/python3/python2/ as well)
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
There's a lot more that's needed for python3 hg --config profiling.statformat=chrome --profile to work, so I'll probably put more changes in this patch soon.
Path | Packages | |||
---|---|---|---|---|
M | mercurial/statprof.py (12 lines) |
Status | Author | Revision | |
---|---|---|---|
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz |
_pathcache = {} | _pathcache = {} | ||||
def simplifypath(path): | def simplifypath(path): | ||||
'''Attempt to make the path to a Python module easier to read by | '''Attempt to make the path to a Python module easier to read by | ||||
removing whatever part of the Python search path it was found | removing whatever part of the Python search path it was found | ||||
on.''' | on.''' | ||||
if path in _pathcache: | if path in _pathcache: | ||||
return _pathcache[path] | return _pathcache[path] | ||||
hgpath = pycompat.fsencode(encoding.__file__).rsplit(os.sep, 2)[0] | hgpath = encoding.__file__.rsplit(os.sep, 2)[0] | ||||
for p in [hgpath] + sys.path: | for p in [hgpath] + sys.path: | ||||
prefix = p + os.sep | prefix = p + os.sep | ||||
if path.startswith(prefix): | if path.startswith(prefix): | ||||
path = path[len(prefix):] | path = path[len(prefix):] | ||||
break | break | ||||
_pathcache[path] = path | _pathcache[path] = path | ||||
return path | return path | ||||
def stackid(stack): | def stackid(stack): | ||||
if not stack: | if not stack: | ||||
return | return | ||||
if stack in stack2id: | if stack in stack2id: | ||||
return stack2id[stack] | return stack2id[stack] | ||||
parent = stackid(stack[1:]) | parent = stackid(stack[1:]) | ||||
myid = len(stack2id) | myid = len(stack2id) | ||||
stack2id[stack] = myid | stack2id[stack] = myid | ||||
id2stack.append(dict(category=stack[0][0], name='%s %s' % stack[0])) | id2stack.append(dict(category=stack[0][0], name=r'%s %s' % stack[0])) | ||||
if parent is not None: | if parent is not None: | ||||
id2stack[-1].update(parent=parent) | id2stack[-1].update(parent=parent) | ||||
return myid | return myid | ||||
# The sampling profiler can sample multiple times without | # The sampling profiler can sample multiple times without | ||||
# advancing the clock, potentially causing the Chrome trace viewer | # advancing the clock, potentially causing the Chrome trace viewer | ||||
# to render single-pixel columns that we cannot zoom in on. We | # to render single-pixel columns that we cannot zoom in on. We | ||||
# work around this by pretending that zero-duration samples are a | # work around this by pretending that zero-duration samples are a | ||||
def poplast(): | def poplast(): | ||||
oldsid = stackid(tuple(laststack)) | oldsid = stackid(tuple(laststack)) | ||||
oldcat, oldfunc = laststack.popleft() | oldcat, oldfunc = laststack.popleft() | ||||
oldtime, oldidx = lastseen.popleft() | oldtime, oldidx = lastseen.popleft() | ||||
duration = sample.time - oldtime | duration = sample.time - oldtime | ||||
if minthreshold <= duration <= maxthreshold: | if minthreshold <= duration <= maxthreshold: | ||||
# ensure no zero-duration events | # ensure no zero-duration events | ||||
sampletime = max(oldtime + clamp, sample.time) | sampletime = max(oldtime + clamp, sample.time) | ||||
samples.append(dict(ph='E', name=oldfunc, cat=oldcat, sf=oldsid, | samples.append(dict(ph=r'E', name=oldfunc, cat=oldcat, sf=oldsid, | ||||
ts=sampletime*1e6, pid=0)) | ts=sampletime*1e6, pid=0)) | ||||
else: | else: | ||||
blacklist.add(oldidx) | blacklist.add(oldidx) | ||||
# Much fiddling to synthesize correctly(ish) nested begin/end | # Much fiddling to synthesize correctly(ish) nested begin/end | ||||
# events given only stack snapshots. | # events given only stack snapshots. | ||||
for sample in data.samples: | for sample in data.samples: | ||||
stack = tuple((('%s:%d' % (simplifypath(frame.path), frame.lineno), | stack = tuple(((r'%s:%d' % (simplifypath(pycompat.sysstr(frame.path)), frame.lineno), | ||||
frame.function) for frame in sample.stack)) | pycompat.sysstr(frame.function)) for frame in sample.stack)) | ||||
qstack = collections.deque(stack) | qstack = collections.deque(stack) | ||||
if laststack == qstack: | if laststack == qstack: | ||||
continue | continue | ||||
while laststack and qstack and laststack[-1] == qstack[-1]: | while laststack and qstack and laststack[-1] == qstack[-1]: | ||||
laststack.pop() | laststack.pop() | ||||
qstack.pop() | qstack.pop() | ||||
while laststack: | while laststack: | ||||
poplast() | poplast() | ||||
for f in reversed(qstack): | for f in reversed(qstack): | ||||
lastseen.appendleft((sample.time, len(samples))) | lastseen.appendleft((sample.time, len(samples))) | ||||
laststack.appendleft(f) | laststack.appendleft(f) | ||||
path, name = f | path, name = f | ||||
sid = stackid(tuple(laststack)) | sid = stackid(tuple(laststack)) | ||||
samples.append(dict(ph='B', name=name, cat=path, ts=sample.time*1e6, | samples.append(dict(ph=r'B', name=name, cat=path, ts=sample.time*1e6, | ||||
sf=sid, pid=0)) | sf=sid, pid=0)) | ||||
laststack = collections.deque(stack) | laststack = collections.deque(stack) | ||||
while laststack: | while laststack: | ||||
poplast() | poplast() | ||||
events = [sample for idx, sample in enumerate(samples) | events = [sample for idx, sample in enumerate(samples) | ||||
if idx not in blacklist] | if idx not in blacklist] | ||||
frames = collections.OrderedDict((str(k), v) | frames = collections.OrderedDict((str(k), v) | ||||
for (k,v) in enumerate(id2stack)) | for (k,v) in enumerate(id2stack)) |