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

一文看得 Linux 性能分析

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

最近線上運行的程序出現(xiàn)性能問題,但通過分析程序源代碼(Code Review),并找不到導致問題的根本原因。所以,只能借助強大的性能分析工具 perf 來找出問題所在。

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

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

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

使用 perf 分析程序性能瓶頸

在介紹 perf 的實現(xiàn)之前,我們先使用 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;
}

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

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

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

$ gcc sample.c -g -o sample

使用 perf 的record 命令來記錄程序的運行情況。

$ sudo perf record -g ./sample sleep 10

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

使用 perf 的report 命令分析程序的運行情況。

$ perf report -g

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

圖片

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

perf 實現(xiàn)原理

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

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

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)計程序中各個函數(shù)的耗時情況,但卻存在很多問題:

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

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

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

perf 就是為了解決上述問題而生的,我們先來介紹一下 perf 的原理。

采樣

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

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

圖片

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

排序

如果程序有成千上萬的函數(shù),那么采樣出來的數(shù)據(jù)可能非常多,這個時候就需要對采樣的數(shù)據(jù)進行排序。

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

圖片

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

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

總結(jié)

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

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

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

2019-03-18 11:15:07

Linux性能網(wǎng)絡

2022-08-01 14:59:57

Web前端后端

2021-10-25 16:01:01

Linux設備樹字符串

2021-05-12 18:22:36

Linux 內(nèi)存管理

2020-09-03 06:35:44

Linux權(quán)限文件

2019-07-01 09:22:15

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

2024-05-11 08:18:49

2023-12-29 15:30:41

內(nèi)存存儲

2024-10-10 17:55:57

LinuxACL訪問控制列表

2021-11-02 10:53:56

Linux機制CPU

2021-12-15 09:32:41

Linux系統(tǒng)負載

2022-04-12 09:05:30

Linux時鐘

2022-03-28 19:19:45

Linux時間子系統(tǒng)

2021-10-06 20:23:08

Linux共享內(nèi)存

2020-10-09 07:56:52

Linux

2023-12-15 15:55:24

Linux線程同步

2022-05-12 13:44:35

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

2022-04-26 06:36:09

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

2021-12-08 22:29:41

經(jīng)營分析體系

2019-09-03 10:05:27

Linux監(jiān)控系統(tǒng)
點贊
收藏

51CTO技術棧公眾號