【问题标题】:How does perf associate events to functions?perf 如何将事件与函数关联起来?
【发布时间】:2017-07-03 22:19:19
【问题描述】:

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

但是要真正获得细粒度的结果,您需要以非常高的速率对计数器进行采样,否则您可能会将计数器与一组函数相关联。 但是读取计数器并将采样数据(计数器、PC、调用堆栈)写入 perf mmap 空间非常麻烦。

我在一些资料中读到,这种采样仅在 PMU 计数器溢出时发生,但这可能非常粗糙,除非我将计数器设置为非常快速地溢出

我在这里缺少什么?

【问题讨论】:

    标签: linux performance linux-kernel perf


    【解决方案1】:

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

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

    perf report 的实际代码在linux/tools/perf/builtin-report.c 中:cmd_report/__cmd_report -> perf_session__process_events -> 一些魔法 -> process_sample_event 记录 perf.data ip (PC) 中提到的所有内容带有hist_entry_iter__add(&iter, &al, rep->max_stack, rep); 的值到带有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 中记录的样本可能很少。但是如果你有数百个样本,你可以找到大多数 cpu-heavy 函数(它们可能有 pareto rule 并且运行大约百分之几十的程序运行时间。当你想查看更小的函数时(大约百分之几的运行时间)时间),使用数千或数万或数千个样本并进行一些统计估计(当您有 100 或 1000 个样本时,您将无法获得运行时间为 0.1% 的函数的正确百分比)。

    【讨论】:

    • 所以,基本上计数被忽略,它只是在溢出事件期间对 PC 的出现进行采样。当事件是 CPU 周期并且有足够的样本时,我可以看到它是如何工作的。但是,例如,当事件是缓存未命中时,它是如何工作的。是否保证缓存未命中中的 ovewflow 事件也将代表一个很好的近似值
    • 基本上在 irq 上的采样计数为零。所有事件都使用相同的 PMU 单元,它们只为不同的事件 ID 设置它。到最近的缓存(每个内核都有自己的 L1 和 L2 缓存)的缓存未命中仍然可以几乎准确地注册(但在某些架构中,事件可能会从 LOAD 命令滑到加载值的使用)。 Offcore/uncore 事件并不像它们在某些资源中那样容易,它们在内核之间共享并使用全局 PMU;将它们关联起来,本地 PMU 的特殊合成事件可用于关联计数和路由中断(但我完全误解了这部分)。
    • 您还可以查看 Andi Kleen 的演示文稿,他为 x86 编写了大量 perf 并编写了 pmu-tools(intel-specific wrapper for perf - github.com/andikleen/pmu-tools);例如halobates.de/modern-pmus-yokohama.pdf“Linux 上的现代 CPU 性能分析”,2011 -“PMU 的基本操作.. 启用事件计数的事件代码 • 达到阈值时中断:允许采样... 经典分析 • 关注帕累托原则 80-20(或根据 Knuth 的 90-10) • 使用循环计数器采样 • 识别最热代码"。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    相关资源
    最近更新 更多