gprof显示一个简单的信号处理程序占用了大量的CPU

时间:2013-12-26 06:09:37

标签: linux performance profiling signals gprof

我使用gprof来分析在linux上运行的程序,该程序使用25ms间隔计时器(由timer_create()创建)来更新全局变量。信号处理程序类似于update_every_25ms(),它调用profile_dummy()来增加grobal变量:

static void update_every_25ms(int sig_nr) { profile_dummy(); }
void profile_dummy(void) { global_var++; }

通过以下方式创建计时器:

timer_t timer;
struct itimerspec itimer;
timer_create(CLOCK_MONOTONIC, NULL, &timer)
itimer.it_interval.tv_sec = 0;
itimer.it_interval.tv_nsec = 25 * 1000 * 1000;
timer_settime(timer, 0, &itimer, NULL);

我的程序做了很多繁重的工作,但gprof显示update_every_25ms()函数占用了CPU使用率为100%的大部分时间,而且这个函数本身每次调用大约需要1.53ms!

当间隔为25ms时,以下是几组gprof输出:

%time  cumulative  self     calls  self    total    name
       seconds     seconds         ms/call ms/call
3.72   116.26      7.76     22963  0.34    0.34     profile_dummy

此处CPU使用率为60%。 为什么profile_dummy()每次调用需要0.34ms?

%time  cumulative  self     calls  self    total    name
       seconds     seconds         ms/call ms/call
9.38   38.87       38.87    25349  0.00    0.00     profile_dummy

此处CPU使用率为100%。 38.87s / 25349 = 1.53ms但是gprof输出0.00,发生了什么?

%time  cumulative  self     calls  self    total    name
       seconds     seconds         ms/call ms/call
6.21   270.58      57.72 59105     0.00    0.00     profile_dummy

此处CPU使用率为90%。 并且57.72s / 59105 = 0.98ms但gprof也输出0.00。

当我将定时器间隔更改为25秒时,这是gprof输出:

%time  cumulative  self     calls  self    total    name
       seconds     seconds         ms/call ms/call
0.01   287.52      0.03  23        1.30    1.30     profile_dummy

该函数只增加一个全局变量,为什么需要1.30ms?

感谢您的回复。

1 个答案:

答案 0 :(得分:0)

我只是想在这里猜测。

gprof每10ms有一个信号中断,此时它会对程序计数器(PC)进行采样。 例程的总自身时间是在该例程中着陆的样本数。 由于它还会计算对例程的调用,因此可以获得每次调用的平均自我时间。

通常,当您的程序被阻止时,例如I / O,睡眠或多任务暂停,PC无意义,因此中断被暂停。 这就是gprof根本无法看到I / O的原因。

但是,如果您有自己的定时器中断,那可能只会屏蔽分析器中断,而不是暂停它,导致在您的定时器中断被解除后应答它,这可能会将PC优先置于您的中断处理程序中。

但这只是猜测。

除非这纯粹是一个学术问题,否则有比gprof更好的分析者。