一:背景
1. 講故事
如果要分析 Linux上的 .NET程序 CPU 爆高,按以往的個(gè)性我肯定是抓個(gè) dump 下來(lái)做事后分析,這種分析模式雖然不重但也不輕,還需要一定的底層知識(shí),那有沒(méi)有傻瓜式的 CPU 爆高分析方式呢?
相信有很多朋友知道 B站713事件,最終就是用 perf 找到了那個(gè)讓 cpu 100% 的 lua 函數(shù),截圖如下:
這里我們也借助 perf 這款工具實(shí)現(xiàn) .NET程序的 cpu 爆高洞察, perf 就不過(guò)多介紹了,它是Linux系統(tǒng)
中提供的一款性能分析工具,類(lèi)似 Windows 的 ETW 跟蹤,所以對(duì)他的了解是非常重要的。
這里要注意的是我們并不直接使用,而是用微軟提供的基于 perf 的高層封裝工具 perfCollect,它不僅能收集 perf 能收集的事件,還能收集 .NET 中的 EventSource 事件,簡(jiǎn)直是福音哈。
PerfCollect 跟蹤
1. 測(cè)試代碼
為了能夠讓 CPU 爆高,我們故意讓其中一個(gè)方法死循環(huán),一個(gè)方法運(yùn)行一段時(shí)間正常結(jié)束,參考代碼如下:
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Task.Run(() =>
{
Test1();
});
Task.Run(() =>
{
Test2();
});
Console.ReadLine();
}
static void Test1()
{
int i = 1;
bool b = false;
while (i > 0)
{
b = !b;
}
}
static void Test2()
{
for (int i = 0; i < short.MaxValue; i++)
{
}
}
}
}
代碼有了就可以 publish 到 centos 上,接下來(lái)在 /etc/profile
中增加一個(gè)環(huán)境變量 export COMPlus_PerfMapEnabled=1
,目的是讓 RIP 能夠成功解析到 C# 的方法名,截圖如下:
有了這些前置基礎(chǔ),接下來(lái)就是把程序跑起來(lái),用 htop 觀(guān)察下 CPU 的利用率。
[root@localhost data2]# vim /etc/profile
[root@localhost data2]# source /etc/profile
[root@localhost data2]# ls
ConsoleApp1 ConsoleApp1.deps.json ConsoleApp1.dll ConsoleApp1.pdb ConsoleApp1.runtimeconfig.json
[root@localhost data2]# dotnet ConsoleApp1.dll
2. 安裝 PerfCollect
剛才也說(shuō)了 PerfCollect
是微軟提供的一款工具,集成了 perf
+ LTTng
兩塊,前者用于捕獲Linux系統(tǒng)級(jí)事件,后者用于捕獲 CoreCLR 以及 EventSource 事件,接下來(lái)就是下載,賦權(quán)限,安裝。
[root@localhost data3]# curl -OL https://aka.ms/perfcollect
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:02 --:--:-- 0
100 68590 100 68590 0 0 17540 0 0:00:03 0:00:03 --:--:-- 72658
[root@localhost data3]# chmod +x perfcollect
[root@localhost data3]# sudo ./perfcollect install
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
epel/x86_64/metalink | 28 kB 00:00:00
* base: ftp.sjtu.edu.cn
* epel: d2lzkl7pfhq30w.cloudfront.net
* extras: mirror.lzu.edu.cn
* updates: mirror.lzu.edu.cn
base | 3.6 kB 00:00:00
docker-ce-stable | 3.5 kB 00:00:00
extras | 2.9 kB 00:00:00
packages-microsoft-com-prod | 1.5 kB 00:00:00
updates | 2.9 kB 00:00:00
Package perf-3.10.0-1160.92.1.el7.x86_64 already installed and latest version
Package zip-3.0-11.el7.x86_64 already installed and latest version
Package unzip-6.0-24.el7_9.x86_64 already installed and latest version
Nothing to do
LTTng already installed.
安裝好之后進(jìn)行 10s 采集,采集完之后就會(huì)生成一個(gè) ConsoleApp.trace.zip
文件,輸出如下:
[root@localhost data3]# ./perfcollect collect ConsoleApp -collectsec 10
Collection started. Collection will automatically stop in 10 second(s). Press CTRL+C to stop early.
...STOPPED.
Starting post-processing. This may take some time.
Generating native image symbol files
...FINISHED
Saving native symbols
...FINISHED
Resolving JIT and R2R symbols
...FINISHED
Exporting perf.data file
...FINISHED
Compressing trace files
...FINISHED
Cleaning up artifacts
...FINISHED
Trace saved to ConsoleApp.trace.zip
最后把 ConsoleApp.trace.zip
復(fù)制到 Windows 平臺(tái)上用 PerfView 分析。
3. Perfview 分析
說(shuō)句良心話(huà),Perfview 真的是太強(qiáng)大了,什么文件都能從中提取有用信息,比如 .dmp,.nettrace 還有這里的 .zip ,用 Perfview 打開(kāi) zip 之后,雙擊 CPU Stacks
選項(xiàng),找到我們的 PID 進(jìn)程即(.NET ThreadPool),截圖如下:
[root@localhost data3]# ps -ef | grep dotnet
root 6027 3171 99 23:33 pts/1 00:02:01 dotnet ConsoleApp1.dll
root 6529 5240 0 23:35 pts/2 00:00:00 grep --color=auto dotnet
雙擊打開(kāi)之后,去掉 GroupPats
信息,可以看到占比最高的是 Program::Test1()
方法。
有朋友可能要問(wèn)這個(gè)信息怎么解讀呢?其實(shí)非常簡(jiǎn)單,perf 也是按照 1ms 采樣一次的方式,所以 10s 的樣本數(shù): 1w =10 * 1000
。
從上圖中可以看到,總的采樣到了 9999
個(gè)樣本,其中 Program::Test1()
占據(jù)了 9993
,占比高達(dá) 99.9%
,到這里我們就定位出了原來(lái)這個(gè)函數(shù)就是 hot 函數(shù)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-576565.html
三:總結(jié)
不知道大家發(fā)現(xiàn)沒(méi)有,在 Windows 上很容易監(jiān)控的東西,在 Linux 上就要麻煩的多,其實(shí)很容易理解,Windows 是微軟的, .NET 也是微軟的,自然是一等公民的存在。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-576565.html

到了這里,關(guān)于用 perfcollect 洞察 Linux 上.NET程序 CPU爆高的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!