使用gprof进行性能分析时的神秘功能_L_lock_154

时间:2015-02-23 11:54:57

标签: c profiling gprof

在分析我的代码时,gprof输出以下内容:

Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name    
 30.69     10.55    10.55                             _L_lock_154
 16.58     16.25     5.70 1126059616     0.00     0.00  double_cmp
 14.25     21.15     4.90    13737     0.36     0.36  bsdi
 10.01     24.59     3.44                             memcpy

(仅限前几行)

占据榜首是一个我不认识的功能,不幸的是谷歌也没有。

可能是什么 - 有谁知道吗?因为它占据了我的时间中的狮子份额,所以我很想知道。

使用mikes建议进行DIY分析,我经常看到这个堆栈回溯:

Program received signal SIGINT, Interrupt.
0xb7fff424 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7fff424 in __kernel_vsyscall ()
#1  0x080ada62 in __write_nocancel ()
#2  0x080859c1 in _IO_new_file_write ()
#3  0x08084b64 in new_do_write ()
#4  0x080861ed in _IO_new_do_write ()
#5  0x080869c5 in _IO_new_file_overflow ()
#6  0x08085f3e in _IO_new_file_xsputn ()
#7  0x080c4d54 in vfprintf ()
#8  0x080b071c in __fprintf_chk ()
#9  0x0805ec36 in fprint_track_hum ()
#10 0x0805efe1 in fprint_hash_tracks ()
#11 0x08049c33 in main (argc=22, argv=0xbfffeac4) at harness.c:537

虽然我没有看到对_L_lock_154的调用,但我开始认为它可能是打印到文件/ stdio.h相关的东西 - 写入文件指针或其他一些锁定。因此,我将尝试禁用所有打印和重新配置文件,看看神秘功能是否消失..

更新#1

不 - 它仍然有点神秘,禁用所有输出到文件/标准输出,但是罪恶的_L_lock_154仍然占用了我10%的时间。可能与从文件中读取有关但我无法在没有输入的情况下运行我的线束。

我真的很惊讶谷歌在此上画了一个空白 - 非常罕见......

更新#2

只是在调用图中运行gprof而不是平面模式 - 它为_L_lock_154吐出了这个:

granularity: each sample hit covers 4 byte(s) for 0.03% of 36.86 seconds

index % time    self  children    called     name
                                                 <spontaneous>
[1]     49.6   11.82    6.45                 _L_lock_154 [1]
                5.84    0.00 1198163721/1198163721     double_cmp [8]
                0.52    0.00 125628587/125628587     fptype_cmp [24]
                0.04    0.00 13096233/13096233     grp_cmp_by_density_descending [52]
                0.04    0.00 3464916/3464916     pdw_ptr_cmp_by_amp [53]
                0.01    0.00   73812/73812       pdw_ptr_cmp_by_idx [89]
                0.00    0.00   71682/9288620     int_cmp [44]
                0.00    0.00  636314/842100      pri_ptr_cmp_by_second_pdw_idx [123]
                0.00    0.00  277089/407783      pri_ptr_cmp_by_first_pdw_idx [124]
                0.00    0.00   76178/76178       window_cmp_by_emitter_id [128]
                0.00    0.00   10147/10147       pri_ptr_cmp_by_first_pdw_toa [137]
-----------------------------------------------

我确定这是想告诉我一些事情,但我不确定如何解释它?我的所有cmp类型函数都与stdlib的qsort一起使用 - 如果_L_lock_154是所有这些调用的父级,它是否意味着它是qsort的别名?

1 个答案:

答案 0 :(得分:3)

好的,gprof对CPU时间进行采样,同时在挂钟时间内随机暂停采样。因此,当gprof表示例程需要30%的时间时,它意味着CPU时间,这可能不到挂钟时间的1%。换句话说,您受I / O约束。因此即使你可以花费0倍的时间,你也永远不会看到差异。 (这就是为什么我贬低“CPU分析” - 它导致经验不足的程序员将注意力集中在无关紧要的事情上。)

如果不清楚,您的程序可能会进行1微秒的实际计算,其中很大一部分包括进入和退出I / O堆栈的例程。一旦它到达I / O堆栈的底部,它可能在出来之前等待99微秒并且再使用CPU 1微秒。 gprof只告诉你如何使用1%的时间,就好像这一切都很重要。

要在随机暂停中获得与gprof相当的结果,您必须丢弃包含__kernel_vsyscall的所有样本。因此,在找到实际使用CPU时间的样本之前,您可能需要采集100个样本。 这是很多工作,但是如果你这样做了,我希望你会在大约30%的非I / O样本上看到Lock例程。

请记住,编写gprof时,是由加州大学伯克利分校的工作人员开设的,这是一个正在开发unix版本的学术环境。 它有一个内置的假设 - 所有I / O都是必要的 I / O. 在真实的用户级软件中,情况往往并非如此。 此外,I / O不是非CPU时间,它只是一个不同的 CPU。 有一个I / O控制器芯片运行该磁盘,端口或你有什么。