偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

一文看得 Linux 性能分析

系統(tǒng) Linux
perf 工具的功能非常強(qiáng)大,但本文并不是介紹 perf 工具的使用,而是介紹 perf 的實(shí)現(xiàn)原理。介紹 perf 使用的文章多如牛毛,但介紹 perf 原理和實(shí)現(xiàn)的卻鳳毛麟角。

最近線上運(yùn)行的程序出現(xiàn)性能問(wèn)題,但通過(guò)分析程序源代碼(Code Review),并找不到導(dǎo)致問(wèn)題的根本原因。所以,只能借助強(qiáng)大的性能分析工具 perf 來(lái)找出問(wèn)題所在。

perf 工具的功能非常強(qiáng)大,但本文并不是介紹 perf 工具的使用,而是介紹 perf 的實(shí)現(xiàn)原理。介紹 perf 使用的文章多如牛毛,但介紹 perf 原理和實(shí)現(xiàn)的卻鳳毛麟角。

但正因?yàn)?perf 功能非常強(qiáng)大,所以其實(shí)現(xiàn)也是非常復(fù)雜的。本文只介紹其中的一個(gè)功能:分析進(jìn)程中的函數(shù)調(diào)用頻率。

接下來(lái),我們先介紹怎么使用 perf 來(lái)分析進(jìn)程中的函數(shù)調(diào)用頻率。

使用 perf 分析程序性能瓶頸

在介紹 perf 的實(shí)現(xiàn)之前,我們先使用 perf 分析一個(gè)簡(jiǎn)單的程序,此程序代碼如下:

// 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;
}

上面的程序很簡(jiǎn)單,我們創(chuàng)建兩個(gè)函數(shù):workload1? 和 workload2?。從代碼可以看出,workload2? 的負(fù)載是 workload1 的2倍。

現(xiàn)在我們使用 perf 來(lái)分析這個(gè)程序的性能瓶頸在哪里。

首先我們將程序編譯成可執(zhí)行文件,編譯時(shí)記得加上-g 參數(shù),這樣 perf 才能獲取到函數(shù)名。

$ gcc sample.c -g -o sample

使用 perf 的record 命令來(lái)記錄程序的運(yùn)行情況。

$ sudo perf record -g ./sample sleep 10

運(yùn)行上面的命令后,將會(huì)生成一個(gè) perf.data 的文件,此文件記錄了 sample 程序運(yùn)行時(shí)的采樣數(shù)據(jù)。

使用 perf 的report 命令分析程序的運(yùn)行情況。

$ perf report -g

結(jié)果如下圖所示:

圖片

從上圖可以看出,函數(shù) workload2(65%)的負(fù)載大概是函數(shù) workload1(35%)的 2 倍,與我們的代碼基本一致。

perf 實(shí)現(xiàn)原理

通過(guò)上面的例子,我們大概知道怎么使用 perf 來(lái)分析程序的性能瓶頸。接下來(lái),我們將會(huì)介紹 perf 的內(nèi)部實(shí)現(xiàn)原理。

來(lái)思考一下,如果讓我們來(lái)設(shè)計(jì)一個(gè)統(tǒng)計(jì)程序中各個(gè)函數(shù)占用 CPU 時(shí)間的方案,應(yīng)該如何設(shè)計(jì)?最簡(jiǎn)單的方案就是:在各個(gè)函數(shù)的開(kāi)始記錄當(dāng)前時(shí)間,然后在函數(shù)執(zhí)行結(jié)束后,使用當(dāng)前時(shí)間減去函數(shù)開(kāi)始執(zhí)行時(shí)的時(shí)間,得到函數(shù)的執(zhí)行時(shí)間總時(shí)長(zhǎng)。如下偽代碼:

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);
}

雖然上述方式可以統(tǒng)計(jì)程序中各個(gè)函數(shù)的耗時(shí)情況,但卻存在很多問(wèn)題:

  • 代碼入侵度高。由于要對(duì)每個(gè)函數(shù)進(jìn)行耗時(shí)記錄,所以必須在調(diào)用函數(shù)前和調(diào)用函數(shù)后加入統(tǒng)計(jì)代碼。
  • 統(tǒng)計(jì)函數(shù)耗時(shí),并不能反映該函數(shù)的真實(shí) CPU 使用率。比如函數(shù)內(nèi)部調(diào)用了導(dǎo)致進(jìn)程休眠的系統(tǒng)調(diào)用(如sleep),這時(shí)函數(shù)實(shí)際上是不使用CPU的,但函數(shù)的耗時(shí)卻統(tǒng)計(jì)了休眠的時(shí)間。
  • 對(duì)性能影響較大。由于程序中所有函數(shù)都加入統(tǒng)計(jì)代碼,所以對(duì)性能的影響是非常大的。

所以我們需要一個(gè)系統(tǒng),它能夠避免上述問(wèn)題:

  • 零代碼入侵。
  • 能夠真實(shí)反映函數(shù)的 CPU 使用率。
  • 對(duì)性能影響較小。

perf 就是為了解決上述問(wèn)題而生的,我們先來(lái)介紹一下 perf 的原理。

采樣

為了減小對(duì)程序性能的影響,perf 并不會(huì)在每個(gè)函數(shù)加入統(tǒng)計(jì)代碼,取而代之的統(tǒng)計(jì)方式是:采樣。

采樣的原理是:設(shè)置一個(gè)定時(shí)器,當(dāng)定時(shí)器觸發(fā)時(shí),查看當(dāng)前進(jìn)程正在執(zhí)行的函數(shù),然后記錄下來(lái)。如下圖所示:

圖片

如上圖所示,每個(gè) cpu-clock? 是一個(gè)定時(shí)器的觸發(fā)點(diǎn)。在 6 次定時(shí)器觸發(fā)點(diǎn)中,函數(shù) func1? 被命中了 3 次,函數(shù) func2? 被命中了 1 次,函數(shù) func3 被命中了 2 次。所以,我們可以推測(cè)出,函數(shù) func1 的 CPU 使用率最高。

排序

如果程序有成千上萬(wàn)的函數(shù),那么采樣出來(lái)的數(shù)據(jù)可能非常多,這個(gè)時(shí)候就需要對(duì)采樣的數(shù)據(jù)進(jìn)行排序。

為了對(duì)采樣數(shù)據(jù)進(jìn)行排序,perf 使用紅黑樹(shù)這種數(shù)據(jù)結(jié)構(gòu),如下圖所示:

圖片

如上圖所示,在 perf 采樣的數(shù)據(jù)中,有 7 個(gè)函數(shù)被統(tǒng)計(jì)了命中次數(shù),perf 使用采樣到的數(shù)據(jù)構(gòu)建一棵紅黑樹(shù)。

根據(jù)紅黑樹(shù)的特性,最右邊的節(jié)點(diǎn)就是被命中最多的函數(shù),這樣就能把程序中 CPU 使用率最高的函數(shù)找出來(lái)。

總結(jié)

由于 perf 的功能非常強(qiáng)大,所以本文也只介紹了 perf 其中一種功能:統(tǒng)計(jì)函數(shù)的 CPU 使用率。

在下一篇文章中,我們將會(huì)介紹 perf 的代碼實(shí)現(xiàn)。Linux 的創(chuàng)始人 Linus 曾經(jīng)說(shuō)過(guò):Read the f**king source code,要真正理解一個(gè)系統(tǒng),只能通過(guò)閱讀其源碼。

責(zé)任編輯:武曉燕 來(lái)源: Linux內(nèi)核那些事
相關(guān)推薦

2019-03-18 11:15:07

Linux性能網(wǎng)絡(luò)

2022-08-01 14:59:57

Web前端后端

2020-09-03 06:35:44

Linux權(quán)限文件

2019-07-01 09:22:15

Linux操作系統(tǒng)硬件

2021-10-25 16:01:01

Linux設(shè)備樹(shù)字符串

2021-05-12 18:22:36

Linux 內(nèi)存管理

2024-05-11 08:18:49

2023-12-29 15:30:41

內(nèi)存存儲(chǔ)

2022-03-28 19:19:45

Linux時(shí)間子系統(tǒng)

2022-04-12 09:05:30

Linux時(shí)鐘

2021-12-15 09:32:41

Linux系統(tǒng)負(fù)載

2020-10-09 07:56:52

Linux

2021-10-06 20:23:08

Linux共享內(nèi)存

2023-12-15 15:55:24

Linux線程同步

2021-11-02 10:53:56

Linux機(jī)制CPU

2024-10-10 17:55:57

LinuxACL訪問(wèn)控制列表

2021-12-08 22:29:41

經(jīng)營(yíng)分析體系

2022-05-12 13:44:35

數(shù)據(jù)分析數(shù)據(jù)

2022-04-26 06:36:09

渠道分析數(shù)據(jù)采集

2020-12-18 11:54:22

Linux系統(tǒng)架構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)