python - 为什么 SIGVTALRM 不在 time.sleep() 内部触发?

标签 python unix signals

我正在尝试使用 SIGVTALRM 对我的 Python 代码进行快照分析,但它似乎并没有在 time.sleep() 和套接字操作。

这是为什么呢?有什么方法可以解决这个问题,这样我就可以在进行阻塞操作时收集样本吗?

我也尝试过使用 ITIMER_PROF/SIGPROFITIMER_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/

相关文章:

python - 将 JS 代码转换为 XML 编码的 AST 树

python - IO错误: File not open for reading python

c++ - 使用信号中止功能实现

android - 如何在一行中输入 adb shell 命令?

Python 2.7 ctrl+c 不确定行为

django - 发送电子邮件时 Django 会发出信号吗?

python 和基于决策树验证业务规则

python - 为什么这个 Numpy 函数链中需要命名表达式?

C 编程 - execlp() 有帮助吗?

qt - 如何在 Loader 的项目中正确连接信号?