我正在尝试使用 SIGVTALRM
对我的 Python 代码进行快照分析,但它似乎并没有在 time.sleep()
和套接字操作。
这是为什么呢?有什么方法可以解决这个问题,这样我就可以在进行阻塞操作时收集样本吗?
我也尝试过使用 ITIMER_PROF
/SIGPROF
和 ITIMER_REAL
/SIGALRM
并且两者似乎都产生类似的结果结果。
我正在测试的代码如下,输出类似于:
$ python profiler-test.py
<module>(__main__:1);test_sampling_profiler(__main__:53): 1
<module>(__main__:1);test_sampling_profiler(__main__:53);busyloop(__main__:48): 1509
请注意,timesleep
函数根本没有显示。
测试代码:
import time
import signal
import collections
class SamplingProfiler(object):
def __init__(self, interval=0.001, logger=None):
self.interval = interval
self.running = False
self.counter = collections.Counter()
def _sample(self, signum, frame):
if not self.running:
return
stack = []
while frame is not None:
formatted_frame = "%s(%s:%s)" %(
frame.f_code.co_name,
frame.f_globals.get('__name__'),
frame.f_code.co_firstlineno,
)
stack.append(formatted_frame)
frame = frame.f_back
formatted_stack = ';'.join(reversed(stack))
self.counter[formatted_stack] += 1
signal.setitimer(signal.ITIMER_VIRTUAL, self.interval, 0)
def start(self):
if self.running:
return
signal.signal(signal.SIGVTALRM, self._sample)
signal.setitimer(signal.ITIMER_VIRTUAL, self.interval, 0)
self.running = True
def stop(self):
if not self.running:
return
self.running = False
signal.signal(signal.SIGVTALRM, signal.SIG_IGN)
def flush(self):
res = self.counter
self.counter = collections.Counter()
return res
def busyloop():
start = time.time()
while time.time() - start < 5:
pass
def timesleep():
time.sleep(5)
def test_sampling_profiler():
p = SamplingProfiler()
p.start()
busyloop()
timesleep()
p.stop()
print "\n".join("%s: %s" %x for x in sorted(p.flush().items()))
if __name__ == "__main__":
test_sampling_profiler()
最佳答案
不确定为什么 time.sleep 以这种方式工作(它是否可以使用 SIGALRM 本身来知道何时恢复?)但是 Popen.wait 不会阻止信号,所以最坏的情况下你可以调用操作系统 sleep 。
关于python - 为什么 SIGVTALRM 不在 time.sleep() 内部触发?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33354755/