用perf来分析睡眠时间

时间:2014-02-13 13:47:26

标签: c linux profiling perf

我一直在寻找一种方法来找出我的计划花费时间的地方。我读了perf tutorial并尝试描述那里描述的睡眠时间。我写了最简单的程序来分析:

#include <unistd.h>
int main() {
  sleep(10);
  return 0; 
}

然后我用perf:

执行它
$ sudo perf record -e sched:sched_stat_sleep -e sched:sched_switch -e sched:sched_process_exit -g -o ~/perf.data.raw ./a.out
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.013 MB /home/pablo/perf.data.raw (~578 samples) ]
$ sudo perf inject -v -s -i ~/perf.data.raw -o ~/perf.data
build id event received for [kernel.kallsyms]: d62870685909222126e7070d2bafdf029f7ed3b6
failed to write feature 2
$ sudo perf report --stdio --show-total-period -i ~/perf.data
Error:
The /home/pablo/perf.data file has no samples!

有人知道如何避免这些错误吗?他们的意思是什么? failed to write feature 2看起来不太友好......

更新:

$ uname -a
Linux debian 3.12-1-amd64 #1 SMP Debian 3.12.9-1 (2014-02-01) x86_64 GNU/Linux

3 个答案:

答案 0 :(得分:11)

来自https://perf.wiki.kernel.org/index.php/Tutorial#Profiling_sleep_times - perf inject -s

的第二个perf命令出现错误消息
$ sudo perf inject -v -s -i ~/perf.data.raw -o ~/perf.data
build id event received for [kernel.kallsyms]: d62870685909222126e7070d2bafdf029f7ed3b6
failed to write feature 2
  

未能写入功能2看起来不太用户友好......

...但它被添加到perf以使错误更加用户友好:http://lwn.net/Articles/460520/“perf:make perf.data更具自我描述性(v5)”作者:Stephane Eranian,2011年9月22日:

+static int do_write_feat(int fd, struct perf_header *h, int type,  ....
+           pr_debug("failed to write feature %d\n", type);

此处列出了所有功能http://lxr.free-electrons.com/source/tools/perf/util/header.h#L13

 15         HEADER_TRACING_DATA     = 1,
 16         HEADER_BUILD_ID,

因此,如果我没有错的话,听起来像perf inject无法写入有关构建ID的信息(来自util / header.c的函数write_build_id()的错误)。有两种情况可能导致错误:调用perf_session__read_build_ids()失败或编写buildid表dsos__write_buildid_table失败(这不是我们的情况,因为没有“写入buildid表失败”错误消息;请检查write_build_id

您可以检查,您是否拥有会话所需的所有构建。清除buildid缓存(rm -rf ~/.debug)并检查是否有最新的vmlinux,并在内核中启用调试信息或kallsyms可能很有用。

评论中的

更新: Pavel说他的pref记录没有写入perf.data的sched:sched_stat_sleep个事件:

sudo perf record -e sched:sched_stat_sleep -e sched:sched_switch -e sched:sched_process_exit -g -o ~/perf.data.raw ./a.out

正如他在his answer中解释的那样,他的默认debian内核已禁用CONFIG_SCHEDSTATS选项与供应商的补丁。自3.11以来,redhat对发布内核中的选项做了同样的事情,这在Redhat Bug 1013225中有解释(Josh Boyer 2013-10-28,评论4):

  

我们切换到仅在调试构建之前启用。它似乎完全被最终的3.11.0版本所关闭,并一直保持关闭。内部测试显示该选项对上下文切换具有非平凡的性能影响。

     

我们可以再次在调试内核中打开它,但我不确定它是否值得。

Josh Poimboeuf 2013-11-04在评论8中表示可以检测到性能影响:

  

在我的测试中,我在各种CPU负载下做了很多上下文切换。启用CONFIG_SCHEDSTATS时,我看到平均上下文切换速度下降了约5-10%。 ...性能影响似乎只发生在CFS后的内核上(&gt; = 2.6.23)。以前的O(1)调度程序似乎没有这个问题。

Fedora于2013年7月12日在Dave Jones的非调试内核中禁用了CONFIG_SCHEDSTAT "[kernel] Disable LATENCYTOP/SCHEDSTATS in non-debug builds."。第一个带有禁用选项的内核:3.11.0-0.rc0.git6.4。

为了使用名称为perfsched:sched_stat_*sched:sched_stat_waitsched:sched_stat_sleep)的任何sched:sched_stat_iowait软件跟踪点事件,我们必须重新编译内核启用CONFIG_SCHEDSTATS选项并替换没有此选项的默认Debian,RedHat或Fedora内核。

谢谢Pavel Davydov。

答案 1 :(得分:7)

我终于找到了如何让它发挥作用。问题是默认的debian内核是在没有一些配置选项的情况下构建的,perf需要能够监控休眠时间。看起来应该启用CONFIG_SCHEDSTATS来生成内核收集调度程序统计信息。这被告知有一些运行时开销。我还启用了CONFIG_SCHED_TRACER和一些锁定跟踪选项,但我不确定它们在我的情况下是否重要。无论如何,没有CONFIG_SCHEDSTATS的调度程序中没有收集统计​​数据(参见内核源代码的kernel/sched/目录)。

此外,Brendan Gregg撰写了一篇非常good article about perf的文章,其中包含大量有用的示例和一些内核选项,可以使perf正常工作。

更新:我在debian中查看了CONFIG_SCHEDSTATS的历史记录。我查看了debian内核补丁并构建了脚本repo:

svn checkout svn://svn.debian.org/svn/kernel/dists/trunk/linux/debian

然后在那里找到CONFIG_SCHEDSTATS选项

$ grep -R CONFIG_SCHEDSTAT config/
config/config:# CONFIG_SCHEDSTATS is not set

此字符串已添加到2008年3月14日的提交10837中的repo中,注释为“debian / config:Do complete reorganization”。此外,在thisthis(感谢 osgx )错误报告中,它被告知CONFIG_LATENCYTOP,CONFIG_SCHEDSTATS选项未启用,因为它们可能会影响内核性能。所以,我认为它从未在默认的debian内核中打开。但是,我还没有找到关于调度程序统计选项的讨论。如果我这样做,我会在这里回信。

答案 2 :(得分:1)

这适用于“openSUSE 13.1(x86_64)”框中的“perf版本3.11.1”。

如果你关心,这是输出:

# ========
# captured on: Sun Feb 16 09:49:38 2014
# hostname : *****************
# os release : 3.11.10-7-desktop
# perf version : 3.11.1
# arch : x86_64
# nrcpus online : 8
# nrcpus avail : 8
# cpudesc : Intel(R) Core(TM) i7-3840QM CPU @ 2.80GHz
# cpuid : GenuineIntel,6,58,9
# total memory : 32945368 kB
# cmdline : /usr/bin/perf inject -v -s -i perf.data.raw -o perf.data 
# event : name = sched:sched_stat_sleep, type = 2, config = 0x48, config1 = 0x0, config2 = 0x
# event : name = sched:sched_switch, type = 2, config = 0x51, config1 = 0x0, config2 = 0x0, e
# event : name = sched:sched_process_exit, type = 2, config = 0x4e, config1 = 0x0, config2 = 
# HEADER_CPU_TOPOLOGY info available, use -I to display
# HEADER_NUMA_TOPOLOGY info available, use -I to display
# pmu mappings: cpu = 4, software = 1, tracepoint = 2, uncore_cbox_0 = 6, uncore_cbox_1 = 7, 
# ========
#
# Samples: 0  of event 'sched:sched_stat_sleep'
# Event count (approx.): 0
#
# Overhead        Period  Command  Shared Object  Symbol
# ........  ............  .......  .............  ......
#


# Samples: 8  of event 'sched:sched_switch'
# Event count (approx.): 80099958776
#
# Overhead        Period  Command      Shared Object             Symbol
# ........  ............  .......  .................  .................
#
   100.00%   80099958776      bla  [kernel.kallsyms]  [k] thread_return
                |
                --- thread_return
                    thread_return
                    do_nanosleep
                    hrtimer_nanosleep
                    SyS_nanosleep
                    system_call_fastpath
                    0x7fbc0dec6570
                    __GI___libc_nanosleep
                    (nil)



# Samples: 0  of event 'sched:sched_process_exit'
# Event count (approx.): 0
#
# Overhead        Period  Command  Shared Object  Symbol
# ........  ............  .......  .............  ......
#


#
# (For a higher level overview, try: perf report --sort comm,dso)
#
}