使用 perf 进行性能监控

Posted

技术标签:

【中文标题】使用 perf 进行性能监控【英文标题】:Performance monitoring with perf 【发布时间】:2017-12-01 18:27:41 【问题描述】:

免责声明:我是 perf 新手,仍在努力学习细节。

我有一个在运行 Linux 的目标系统上运行的可执行文件。我想使用 perf 来分析/监控它随着时间的推移的性能。出于争论的原因,我试图证明我当前从 top 和 collectD 测量的 CPU 利用率可以通过 perf 监控来替换,这将产生更精细的数据。

由于我们试图随着时间的推移得到一个情节,我一直在使用perf record -e cycles -p <pid>。之后我可以通过perf report 获取要显示的数据。

问题:

    仅使用perf report 显示数据会显示以下内容的摘要 我采取的整个数据集正确吗? 如果我运行perf report -D,我会得到所有数据的转储。 (作为一个附带问题,时间戳是 ns 中的正常运行时间正确吗?)现在我假设样本基于可以在perf record 中设置的频率,对吗?我通过获取时间戳的时间增量遇到了问题,它似乎是以随机间隔记录的。 一旦我转储数据,这里就没有任何东西真正喊出“这是你的计数!!”所以假设转储中的“周期”字段是原始计数。这是真的?这意味着如果 period = 100,我可以假设对于那个间隔,我的程序使用了 100 个周期?此外,我开始觉得这不仅适用于应用程序,而且适用于程序进行的每个库或内核调用。 IE。如果调用了 malloc,则将记录一个不同的事件,概述调用周期。因此,总体而言,我如何才能得出持续时间或事件 + 事件的周期数 + 它实际上来自该字段的哪个事件,才能真正衡量 CPU 利用率?

如果 perf 的这个应用程序不是它想要做的,那么我也想知道为什么不呢?此外,我认为这种相同类型的分析对于所有其他类型的统计数据都很有用,因为您可以在运行代码中发生异常时及时查明。仅供参考,我在 1 秒时针对***收集运行 perf。我这样做是因为我想将***输出与 perf 输出进行比较。任何见解都会有所帮助,因为正如我所说,我仍在学习这个强大的工具并且是新手。

(Linux内核版本:3.10.82)

【问题讨论】:

【参考方案1】:

答案 #1

大部分是的。 perf report 确实向您显示了收集到的跟踪的摘要。 perf record 收集的样本被保存到一个二进制文件中,默认情况下,perf.dataperf report 命令读取此文件并生成简明的执行配置文件。默认情况下,样本按样本最多的函数排序。但是,您也可以使用此报告进行更详细的分析。

回答 #2

理想情况下,您应该使用perf script -D 来跟踪所有数据。时间戳以 微秒 为单位。虽然,在比您指定的内核更新的内核中,在命令行开关 (-ns) 的帮助下,您也可以以 纳秒 显示时间。这是源代码-

Timestamp

如果不看看你得到了什么样的“增量”,就很难判断这一点。请记住,收集样本的时间通常是经过调整的。有两种方法可以指定采集样本的速率 --

您可以使用perf record (--c for count) 指定收集样本的时间段。这意味着对于您正在测量的事件的每 c 个事件,您将有一个样本。然后,您可以修改采样周期并测试各种值。这意味着每发生两次您正在测量的事件,计数器就会溢出,您将记录一个样本。

表示采样周期的另一种方式是指定每秒采样的平均速率(频率) - 您可以使用perf record -F 来执行此操作。所以perf record -F 1000每秒将记录大约1000个样本,这些样本将在事件对应的硬件/PMU计数器溢出时生成。这意味着内核将动态调整采样周期。您将在不同的随机时刻获得采样时间。

您可以在此处查看代码:

How perf dynamically updates time

答案 #3

为什么不呢?理想情况下,如果您执行perf report 并进行更深入的分析,您应该获得收集的事件样本的数量。此外,当您执行perf record 并完成记录样本时,您将在命令行上收到有关与您测量的事件相对应的收集样本数量的通知。 (这可能在您使用的内核模块中不可用,如果可能,我建议您切换到更新的 linux 版本!)。 样本数应该是原始计数,而不是周期。

如果您的周期是 100 - 这意味着在整个跟踪期间,perf 每 100 个事件记录一次。这意味着,如果在跟踪期间总共发生了 1000 个事件,perf 大约收集了事件 1、100、200、300...1000。

是的,记录的样本不仅来自应用程序。事实上,您可以使用这样的开关:perf record -e <event-name:u> or <event-name:k>(u 代表用户空间,k 代表内核)来记录事件。此外,perf 还记录了来自共享库的样本。 (请参阅perf 手册页了解更多详情)。

正如我之前所说,perf report 应该是计算perf 记录的事件cycles 的样本数的理想工具。收集/记录的事件数量并不准确,因为硬件根本不可能记录所有cycle 事件。这是因为记录和准备所有事件的详细信息需要内核维护一个环形缓冲区,当计数器溢出时,该缓冲区会定期写入。这种对缓冲区的写入是通过中断发生的。它们占用了 CPU 时间的一小部分——这段时间丢失了,并且可以用来记录现在由于 CPU 忙于处理中断而丢失的事件。不过即便如此,您也可以通过perf 获得非常好的估计。

结论

perf 考虑到我们目前手头的硬件资源的限制,尤其会做它打算做的事情。我建议阅读每个命令的手册页以更好地理解。

问题

    我假设您正在查看perf report。我还假设您在谈论perf report 中的开销%。从理论上讲,它可以被认为是您指定的从最高到最少出现的数据排列。但是,您需要考虑和理解许多基本细节才能正确理解输出。它表示哪个函数的开销最大(就该函数中发生的事件数量而言)。在所有函数及其开销之间,还存在基于哪个函数调用哪个函数的父子关系。请使用Perf Report链接了解更多信息。

    如您所知,事件已被采样,而不是计数。所以你不能准确地得到事件的数量,但是你会得到样本的数量,并且根据收集样本的调整频率,你也会得到事件数量的原始计数(一切都应该通过@ 987654347@ 输出)。

【讨论】:

来自 #2:我看到的增量来自 PERF_RECORD_SAMPLE 的原始转储 greping。我认为这是我正在寻找以衡量性能的事件。它几乎看起来像是事件从最少发生到最高发生的总结,然后时间戳是事件第一次发生的时间。我所指的增量是采用 T(I) - T(i-1),因为我认为这是以固定周期采样的事件。但经过研究和一些自我说服,这似乎只是,正如我之前提到的,事件摘要的列表。对吗? 从#3开始:如果我改变了我所做的周期,那么我会得到一个周期性事件。不过,如何从该数据集中提取我的事件?例如,如果我正在记录周期和缓存未命中;我要寻找什么来提取这些数据?我的主要目标是获得每个间隔类型图的周期。所以我通过时间增量来获得我的间隔,但是我如何获得事件的原始计数,以便我可以随着时间的推移绘制它以查看瓶颈? 嗨@Sharki,我已经为你的问题添加了一些细节。

以上是关于使用 perf 进行性能监控的主要内容,如果未能解决你的问题,请参考以下文章

Linux系统性能监控分析工具perf

动态监控 rdtsc 的性能

perf4j+logback配置 可使用注解

对SQLSERVER进行性能监控

使用 perf 监控每个 CPU 的内存访问

使用performance进行网页性能监控