我想记录每个函数使用的CPU时间。需要注意的是,我只想记录函数本身使用的时间,而不是函数调用的函数所使用的CPU时间,以及我的脚本也可以跟踪的函数。例如如果函数foo和bar都被我的脚本跟踪并且函数foo的总cpu时间是2000,但函数foo调用函数栏三次,每次花费500 cpu时间,那么我希望看到以下结果:
function cputime call count
foo 500 1
bar 1500 3
现在我有以下dtrace脚本来获取每个函数的总cpu时间,但我还没有任何关于如何更改它的引导,以便我得到如上所述的cpu时间结果。 (注意调用计数和输出格式化还没有出现在脚本中,但是一旦我掌握了cpu时间信息,就很容易添加。)
#!/usr/sbin/dtrace -s
pid$1:$2::entry
{
++self->call_depth[probefunc];
self->start[probefunc, self->call_depth[probefunc]] = timestamp;
self->vstart[probefunc, self->call_depth[probefunc]] = vtimestamp;
}
pid$1:$2::return
/self->start[probefunc, self->call_depth[probefunc]]/
{
@function_walltime[probefunc] = sum(timestamp - self->start[probefunc, self->call_depth[probefunc]]);
self->start[probefunc, self->call_depth[probefunc]] = 0;
@function_cputime[probefunc] = sum(vtimestamp - self->vstart[probefunc, self->call_depth[probefunc]]);
self->vstart[probefunc, self->call_depth[probefunc]] = 0;
--self->call_depth[probefunc];
}
答案 0 :(得分:1)
希望以下脚本可以提供帮助:
#!/usr/sbin/dtrace -qs
pid$1:$2::entry
{
self->vstart[probefunc] = vtimestamp;
}
pid$1:$2::return
{
this->cputime = vtimestamp - self->vstart[probefunc];
/* Sub the caller function CPU time */
@function_cputime[ufunc(ucaller)] = sum(-(this->cputime));
/* Add the callee function (current function) CPU time */
@function_cputime[ufunc(uregs[R_PC])] = sum(this->cputime);
/* Add the callee function (current function) count */
@function_count[ufunc(uregs[R_PC])] = sum(1);
}
答案 1 :(得分:0)
这是我最终使用的程序:
#!/usr/sbin/dtrace -s
#pragma option quiet
pid$1:$2::entry
/self->start[probefunc] == 0/
{
this->call_depth = self->call_depth++;
self->func_pcs[this->call_depth] = uregs[R_PC];
self->start[probefunc] = timestamp;
self->vstart[probefunc] = vtimestamp;
@function_entry_count[ufunc(uregs[R_PC])] = count();
}
pid$1:$2::return
/self->start[probefunc]/
{
this->call_depth = --self->call_depth;
this->wall_elapsed = timestamp - self->start[probefunc];
self->start[probefunc] = 0;
this->cpu_elapsed = vtimestamp - self->vstart[probefunc];
self->vstart[probefunc] = 0;
@function_walltime_inc[ufunc(uregs[R_PC])] = sum(this->wall_elapsed);
@function_walltime_exc[ufunc(uregs[R_PC])] = sum(this->wall_elapsed);
@function_cputime_inc[ufunc(uregs[R_PC])] = sum(this->cpu_elapsed);
@function_cputime_exc[ufunc(uregs[R_PC])] = sum(this->cpu_elapsed);
@function_return_count[ufunc(uregs[R_PC])] = count();
}
pid$1:$2::return
/this->call_depth > 0/
{
this->caller_pc = self->func_pcs[this->call_depth - 1];
@function_walltime_exc[ufunc(this->caller_pc)] = sum(-(this->wall_elapsed));
@function_cputime_exc[ufunc(this->caller_pc)] = sum(-(this->cpu_elapsed));
}
dtrace:::END
{
/* normalize to millisecons */
normalize(@function_walltime_inc, 1000000);
normalize(@function_walltime_exc, 1000000);
normalize(@function_cputime_inc, 1000000);
normalize(@function_cputime_exc, 1000000);
printf("\n");
printf("%-60s %21s %21s %25s\n", "", "INCLUSIVE", "EXCLUSIVE", "CALL COUNT");
printf("%-60s %10s %10s %10s %10s %12s %12s\n",
"MODULE`FUNCTION", "WALL [ms]", "CPU [ms]", "WALL [ms]", "CPU [ms]", "ENTRY", "RETURN");
printa("%-60A %@10d %@10d %@10d %@10d %@12d %@12d\n",
@function_walltime_inc, @function_cputime_inc,
@function_walltime_exc, @function_cputime_exc,
@function_entry_count, @function_return_count);
}
注意:我跟踪函数入口计数和返回计数,因为某些函数dtrace无法使函数返回正常,这完全扰乱了调用堆栈,因此完成了独占时间。打印两个计数后,可以识别有问题的功能,并在必要时从跟踪中删除。