Redian新闻
>
一文看懂 Linux 性能分析|perf 原理

一文看懂 Linux 性能分析|perf 原理

公众号新闻

最近线上运行的程序出现性能问题,但通过分析程序源代码(Code Review),并找不到导致问题的根本原因。所以,只能借助强大的性能分析工具 perf 来找出问题所在。

perf 工具的功能非常强大,但本文并不是介绍 perf 工具的使用,而是介绍 perf 的实现原理。介绍 perf 使用的文章多如牛毛,但介绍 perf 原理和实现的却凤毛麟角。

但正因为 perf 功能非常强大,所以其实现也是非常复杂的。本文只介绍其中的一个功能:分析进程中的函数调用频率

接下来,我们先介绍怎么使用 perf 来分析进程中的函数调用频率。

使用 perf 分析程序性能瓶颈

在介绍 perf 的实现之前,我们先使用 perf 分析一个简单的程序,此程序代码如下:

// sample.c

void workload1()
{
    int i, c = 0;

    for (i = 0; i < 100000000; i++) {
        c += i * i;
        c -= i * 100;
        c += i * i * i / 100;
    }
}

void workload2()
{
    int i, c = 0;

    for (i = 0; i < 200000000; i++) {
        c += i * i;
        c -= i * 100;
        c += i * i * i / 100;
    }
}

int main(int argc, char *argv[])
{
    workload1();
    workload2();
    return 0;
}

上面的程序很简单,我们创建两个函数:workload1 和 workload2。从代码可以看出,workload2 的负载是 workload1 的2倍。

现在我们使用 perf 来分析这个程序的性能瓶颈在哪里。

  • 首先我们将程序编译成可执行文件,编译时记得加上 -g 参数,这样 perf 才能获取到函数名。
$ gcc sample.c -g -o sample
  • 使用 perf 的 record 命令来记录程序的运行情况。
$ sudo perf record -g ./sample sleep 10

运行上面的命令后,将会生成一个 perf.data 的文件,此文件记录了 sample 程序运行时的采样数据。

  • 使用 perf 的 report 命令分析程序的运行情况。
$ perf report -g

结果如下图所示:

从上图可以看出,函数 workload2(65%)的负载大概是函数 workload1(35%)的 2 倍,与我们的代码基本一致。

perf 实现原理

通过上面的例子,我们大概知道怎么使用 perf 来分析程序的性能瓶颈。接下来,我们将会介绍 perf 的内部实现原理。

来思考一下,如果让我们来设计一个统计程序中各个函数占用 CPU 时间的方案,应该如何设计?最简单的方案就是:在各个函数的开始记录当前时间,然后在函数执行结束后,使用当前时间减去函数开始执行时的时间,得到函数的执行时间总时长。如下伪代码:

void func1()
{
    ...
}

void func2()
{
    ...
}

int main(int argc, char *argv[])
{
    int start_time, total_time;
  
    start_time = now();
    func1();
    total_time = now() - start_time;
    printf("func1() spent %d\n", total_time);

    start_time = now();
    func2();
    total_time = now() - start_time;
    printf("func2() spent %d\n", total_time);
}

虽然上述方式可以统计程序中各个函数的耗时情况,但却存在很多问题:

  1. 代码入侵度高。由于要对每个函数进行耗时记录,所以必须在调用函数前和调用函数后加入统计代码。
  2. 统计函数耗时,并不能反映该函数的真实 CPU 使用率。比如函数内部调用了导致进程休眠的系统调用(如sleep),这时函数实际上是不使用CPU的,但函数的耗时却统计了休眠的时间。
  3. 对性能影响较大。由于程序中所有函数都加入统计代码,所以对性能的影响是非常大的。

所以我们需要一个系统,它能够避免上述问题:

  1. 零代码入侵。
  2. 能够真实反映函数的 CPU 使用率。
  3. 对性能影响较小。

perf 就是为了解决上述问题而生的,我们先来介绍一下 perf 的原理。

采样

为了减小对程序性能的影响,perf 并不会在每个函数加入统计代码,取而代之的统计方式是:采样。

采样的原理是:设置一个定时器,当定时器触发时,查看当前进程正在执行的函数,然后记录下来。如下图所示:

如上图所示,每个 cpu-clock 是一个定时器的触发点。在 6 次定时器触发点中,函数 func1 被命中了 3 次,函数 func2 被命中了 1 次,函数 func3 被命中了 2 次。所以,我们可以推测出,函数 func1 的 CPU 使用率最高。

排序

如果程序有成千上万的函数,那么采样出来的数据可能非常多,这个时候就需要对采样的数据进行排序。

为了对采样数据进行排序,perf 使用红黑树这种数据结构,如下图所示:

如上图所示,在 perf 采样的数据中,有 7 个函数被统计了命中次数,perf 使用采样到的数据构建一棵红黑树。

根据红黑树的特性,最右边的节点就是被命中最多的函数,这样就能把程序中 CPU 使用率最高的函数找出来。

总结

由于 perf 的功能非常强大,所以本文也只介绍了 perf 其中一种功能:统计函数的 CPU 使用率。

在下一篇文章中,我们将会介绍 perf 的代码实现。Linux 的创始人 Linus 曾经说过:Read the f**king source code,要真正理解一个系统,只能通过阅读其源码。

- EOF -


加主页君微信,不仅Linux技能+1

主页君日常还会在个人微信分享Linux相关工具资源精选技术文章,不定期分享一些有意思的活动岗位内推以及如何用技术做业余项目

加个微信,打开一扇窗


推荐阅读  点击标题可跳转

1、Linux 性能分析工具汇总

2、Linux 6.0 正式发布

3、Linux 内核源码中最常见的数据结构之【mutex】


看完本文有收获?请分享给更多人

推荐关注「Linux 爱好者」,提升Linux技能

点赞和在看就是最大的支持❤️

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
大浪淘沙:一文看懂内存芯片的发展史美国多所院校公布2022新生录取数据,一文看懂今年申请趋势!澳洲3种技术移民一文看懂!哪个适合你?下一个“嫖娼”的会是谁?在澳洲读金融&商科,如何拿PR?一文看懂!一文看懂!美国绿卡申请流程与技巧一文看懂MEMS麦克风技术“供销社”大火:一文看懂它的过去、现在和未来Does the third world benefit from the US-China confrontation?一文看得 Linux 性能分析|perf原理如何在 Arch Linux 中安装 OpenOffice(新手指南) | Linux 中国刷脸支付与指纹支付有什么区别?是否安全?一文看懂!大彻大悟:5个人生哲理一文看懂光伏赛道为何分化一文看懂美国大学的「不定专业」该如何申请?一文看懂 Linux 性能分析|perf 源码实现Rosalía 登意大利版《VOGUE》封面!谁说VR/AR不行了?最全产业链报告,一文看懂国内外厂商布局【附下载】| 智东西内参244页云计算蓝皮书,9大趋势7个细分行业一文看懂【附下载】| 智东西内参关于 Linux 和 Git 的创造者 Linus Torvalds 的 20 件趣事 | Linux 中国一文看懂|Linux内核反向映射机制原理一文看懂汽车芯片产业链无性婚姻,为了身份嫁给了白老头--美低端生活(十)运动产生多巴胺?怎样正确清洗羊毛衫?一文看懂→字节跳动基础架构团队参会报告:一文看懂VLDB'22技术趋势及精选论文电影赏析|Please Remember Me运维必学:一文看懂全局负载均衡与 CDN 内容分发在 Linux 中使用 “Converter” GUI 工具转换和操作图像 | Linux 中国让120亿互联设备畅通“交流”,一文看懂物联网协议最新风向!一文看懂分布式链路监控系统贼干干货:Linux 性能分析工具汇总香港加入全球“抢人”大战,一文看懂来港几大途径和香港优势解码梦天|一文看懂梦天实验舱
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。