perf如何将事件关联到函数?

时间:2017-02-15 10:08:35

标签: linux performance linux-kernel perf

更准确地说,perf工具如何将PMU事件与功能相关联 我已经意识到,当内核perf子系统记录事件计数器时,它还会记录程序计数器(PC),以便它可以将计数与函数相关联。

然而,为了获得精细的结果,您需要以非常高的速率对计数器进行采样,否则您可以将计数器与一组函数相关联。 但读取计数器并将采样数据(计数器,PC,调用堆栈)写入perf mmap空间是非常具有侵入性的。

我在某些消息来源中读到,这种采样只发生在PMU计数器溢出时,但这可能非常粗略,除非我将计数器设置为非常快速地溢出

我在这里失踪了什么?

1 个答案:

答案 0 :(得分:4)

perf recordstatistical profiling tool,它会在一定数量的计数之后编程硬件性能事件监视器单元(PMU)溢出(例如用-e cycles -c 1000000写入-1000000来计数并启用计数循环;使用-F或没有freq / period参数,它将自动调整值),在溢出中断perf将重新编程它以进行下一次计数。因此,它每秒将有数百或数千个事件。或者它可以使用OS定时器中断(-e task-clock)来获取周期性样本。在每个样本(或来自硬件PMU的中断)上,perf将记录当前PC(EIP)和/或callstack;并且它不记录计数器的当前值(使用perf script or perf script -D检查存储在perf.data中的数据的完全转储;或code of sample event dumping - 有sample->ip但不是PMU的当前计数。

perf report将解析perf.data以将所有PC记录在其中。它将计算每台PC的采样次数,以构建直方图[PC] -> sample_count。每台PC都将与其所属的确切功能相关联(性能报告将解析内存映射,因为mmap事件也记录在perf.data中,打开每个使用的二进制文件,查找每个二进制文件的符号表。)

perf report的实际代码位于linux/tools/perf/builtin-report.ccmd_report / __cmd_report - > perf_session__process_events - >一些魔术 - > process_sample_event将带有ip的perf.data hist_entry_iter__add(&iter, &al, rep->max_stack, rep);(PC)值中提及的所有内容记录到hist_iter__report_callback的直方图中:

hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
. . . (perf/util/annotate.c) __symbol__inc_addr_samples
  611         h->addr[offset]++;

然后它将输出收集的直方图与report__browse_hists - > perf_evlist__tty_browse_hists - > hists__fprintf_nr_sample_events(hists, rep, evname, stdout);

每个样本都已经与精确函数相关联(由于CPU的无序性和不精确的PMU溢出事件,因此其中的位不精确指令),这就是statistical profiling works的方法。当您的程序运行时间很短(小于秒)和/或采样频率太低时,您可能在perf.data中记录的样本很少。但是如果你有超过几百个样本,你可以找到大多数重量级的函数(它们可能有pareto rule并运行大约几十个百分点的程序运行时间。当你想看到更小的函数时(大约几个百分点)运行时间),使用数千或数十或数千个样本并进行一些统计估计(当你有100或1000个样本时,你将得不到正确的函数百分比,运行时间为0.1%)。