mirror of
https://github.com/facebook/sapling.git
synced 2024-10-09 16:31:02 +03:00
e8b8a87f30
Summary: If the pympler memory profiler is available, let's allow using SIGUSR2 to dump memory information in live Mercurial processes. Reviewed By: quark-zju Differential Revision: D6905664 fbshipit-source-id: fbfa8e538d12a52cf6e4f405ff701f542888cd7f
79 lines
2.2 KiB
Python
79 lines
2.2 KiB
Python
# sigtrace.py
|
|
#
|
|
# Copyright 2017 Facebook, Inc.
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
"""sigtrace - dump stack and memory traces on signal
|
|
|
|
By default, SIGUSR1 will make hg dump stacks of all threads and SIGUSR2 will
|
|
dump memory traces. All traces are dumped to /tmp by default.
|
|
|
|
Config::
|
|
|
|
[sigtrace]
|
|
signal = USR1
|
|
memsignal = USR2
|
|
pathformat = /tmp/trace-%(pid)s-%(time)s.log
|
|
mempathformat = /tmp/memtrace-%(pid)s-%(time)s.log
|
|
"""
|
|
|
|
import os
|
|
import signal
|
|
import sys
|
|
import time
|
|
import traceback
|
|
|
|
from mercurial import (
|
|
registrar,
|
|
)
|
|
|
|
pathformat = '/tmp/trace-%(pid)s-%(time)s.log'
|
|
mempathformat = '/tmp/memtrace-%(pid)s-%(time)s.log'
|
|
|
|
configtable = {}
|
|
configitem = registrar.configitem(configtable)
|
|
|
|
configitem('sigtrace', 'pathformat', default=pathformat)
|
|
configitem('sigtrace', 'signal', default='USR1')
|
|
configitem('sigtrace', 'mempathformat', default=mempathformat)
|
|
configitem('sigtrace', 'memsignal', default='USR2')
|
|
|
|
def printstacks(sig, currentframe):
|
|
content = ''
|
|
for tid, frame in sys._current_frames().iteritems():
|
|
content += ('Thread %s:\n%s\n'
|
|
% (tid, ''.join(traceback.format_stack(frame))))
|
|
|
|
with open(pathformat % {'time': time.time(), 'pid': os.getpid()}, 'w') as f:
|
|
f.write(content)
|
|
|
|
memorytracker = []
|
|
def printmemory(sig, currentframe):
|
|
try:
|
|
from pympler import muppy, summary
|
|
muppy.get_objects
|
|
except ImportError:
|
|
return
|
|
|
|
all_objects = muppy.get_objects()
|
|
sum1 = summary.summarize(all_objects)
|
|
path = mempathformat % {'time': time.time(), 'pid': os.getpid()}
|
|
with open(path, 'w') as f:
|
|
f.write('\n'.join(summary.format_(sum1, limit=50, sort='#')))
|
|
|
|
def uisetup(ui):
|
|
global pathformat, mempathformat
|
|
pathformat = ui.config('sigtrace', 'pathformat')
|
|
mempathformat = ui.config('sigtrace', 'mempathformat')
|
|
signame = ui.config('sigtrace', 'signal')
|
|
sig = getattr(signal, 'SIG' + signame, None)
|
|
if sig is not None:
|
|
signal.signal(sig, printstacks)
|
|
|
|
sig2name = ui.config('sigtrace', 'memsignal')
|
|
sig2 = getattr(signal, 'SIG' + sig2name, None)
|
|
if sig2:
|
|
signal.signal(sig2, printmemory)
|