用 perfcollect 洞察 Linux 上.NET程序 CPU爆高

perfcollect,洞察,linux,net,程序,cpu · 浏览次数 : 511

小编点评

## Summary of the article and the discussion **Problem:** * Linux 上监控 CPU 使用率异常高,需要进行分析。 * 通常方法是抓取 dump 下分析,但需要一定的底层知识。 * 本文介绍了使用 perf 分析 .NET 程序的快速方法。 **Key points:** * 使用 perf 跟踪 .NET 程序,可以快速定位 CPU 使用率异常的函数。 * perf 可以收集 perf 和 LTTng 两个工具,方便分析程序的性能。 * 该方法无需直接访问 .NET 内的内部机制,简化了分析过程。 **Benefits:** * 快速定位问题。 * 减少对 .NET 内的深入了解。 * 使用工具可方便地收集和分析性能数据。 **Additional points:** * 该方法假设用户已经安装了 perf 和 LTTng 工具。 * 该方法仅供参考,实际分析需要根据具体情况进行调整。 **In conclusion,** * 使用 perf 可以快速分析 Linux 上的 .NET 程序,方便定位 CPU 使用率异常的函数。 * 该方法不需要直接访问 .NET 内的内部机制,简化了分析过程。 * 用户需要根据实际情况进行调整,才能获得更准确的结果。

正文

一:背景

1. 讲故事

如果要分析 Linux上的 .NET程序 CPU 爆高,按以往的个性我肯定是抓个 dump 下来做事后分析,这种分析模式虽然不重但也不轻,还需要一定的底层知识,那有没有傻瓜式的 CPU 爆高分析方式呢?

相信有很多朋友知道 B站713事件,最终就是用 perf 找到了那个让 cpu 100% 的 lua 函数,截图如下:

这里我们也借助 perf 这款工具实现 .NET程序的 cpu 爆高洞察, perf 就不过多介绍了,它是Linux系统中提供的一款性能分析工具,类似 Windows 的 ETW 跟踪,所以对他的了解是非常重要的。

这里要注意的是我们并不直接使用,而是用微软提供的基于 perf 的高层封装工具 perfCollect,它不仅能收集 perf 能收集的事件,还能收集 .NET 中的 EventSource 事件,简直是福音哈。

PerfCollect 跟踪

1. 测试代码

为了能够让 CPU 爆高,我们故意让其中一个方法死循环,一个方法运行一段时间正常结束,参考代码如下:


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 上,接下来在 /etc/profile 中增加一个环境变量 export COMPlus_PerfMapEnabled=1 ,目的是让 RIP 能够成功解析到 C# 的方法名,截图如下:

有了这些前置基础,接下来就是把程序跑起来,用 htop 观察下 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

刚才也说了 PerfCollect 是微软提供的一款工具,集成了 perf + LTTng 两块,前者用于捕获Linux系统级事件,后者用于捕获 CoreCLR 以及 EventSource 事件,接下来就是下载,赋权限,安装。


[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.

安装好之后进行 10s 采集,采集完之后就会生成一个 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 复制到 Windows 平台上用 PerfView 分析。

3. Perfview 分析

说句良心话,Perfview 真的是太强大了,什么文件都能从中提取有用信息,比如 .dmp,.nettrace 还有这里的 .zip ,用 Perfview 打开 zip 之后,双击 CPU Stacks 选项,找到我们的 PID 进程即(.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

双击打开之后,去掉 GroupPats 信息,可以看到占比最高的是 Program::Test1() 方法。

有朋友可能要问这个信息怎么解读呢?其实非常简单,perf 也是按照 1ms 采样一次的方式,所以 10s 的样本数: 1w =10 * 1000

从上图中可以看到,总的采样到了 9999 个样本,其中 Program::Test1() 占据了 9993,占比高达 99.9%,到这里我们就定位出了原来这个函数就是 hot 函数。

三:总结

不知道大家发现没有,在 Windows 上很容易监控的东西,在 Linux 上就要麻烦的多,其实很容易理解,Windows 是微软的, .NET 也是微软的,自然是一等公民的存在。

图片名称

与用 perfcollect 洞察 Linux 上.NET程序 CPU爆高相似的内容:

用 perfcollect 洞察 Linux 上.NET程序 CPU爆高

## 一:背景 ### 1. 讲故事 如果要分析 Linux上的 .NET程序 CPU 爆高,按以往的个性我肯定是抓个 dump 下来做事后分析,这种分析模式虽然不重但也不轻,还需要一定的底层知识,那有没有傻瓜式的 CPU 爆高分析方式呢? 相信有很多朋友知道 **B站713事件**,最终就是用 p

用 KV 缓存量化解锁长文本生成

很高兴和大家分享 Hugging Face 的一项新功能: KV 缓存量化 ,它能够把你的语言模型的速度提升到一个新水平。 太长不看版: KV 缓存量化可在最小化对生成质量的影响的条件下,减少 LLM 在长文本生成场景下的内存使用量,从而在内存效率和生成速度之间提供可定制的权衡。 你是否曾尝试过用语

用 Sentence Transformers v3 训练和微调嵌入模型

Sentence Transformers 是一个 Python 库,用于使用和训练各种应用的嵌入模型,例如检索增强生成 (RAG)、语义搜索、语义文本相似度、释义挖掘 (paraphrase mining) 等等。其 3.0 版本的更新是该工程自创建以来最大的一次,引入了一种新的训练方法。在这篇博

用Python脚本迁移MongoDB数据到金仓-kingbase数据库

1、首先需要明确MongoDB与kingbase的对应关系,collection相当于table,filed相当于字段,根据这个对应关系创建表; 此次迁移的MongoDB里的数据字段是:_id(自动生成的objectid),image(转成二进制存储的文档) 所以在金仓里创建表 create tab

用.NET代码生成JSON Schema 验证器

问题 对于验证复杂JSON数据是否合法的需求,通常的解决方式是标准JSON Schema,.Net下有对应的JSON Schema实现库。应用程序通常需要将标准JSON schema传入实现库,来做后续的数据验证。这里有一种情况,就是如果使用者不太了解标准JSON Schema格式,但又希望能在自己

用python字典统计CSV数据

1.用python字典统计CSV数据的步骤和代码示例 为了使用Python字典来统计CSV数据,我们可以使用内置的csv模块来读取CSV文件,并使用字典来存储统计信息。以下是一个详细的步骤和完整的代码示例: 1.1步骤 (1)导入csv模块。 (2)打开CSV文件并读取数据。 (3)初始化一个空字典

【ESP32】制作 Wi-fi 音箱(HTTP + I2S 协议)

用 Wifi 来传输音频数据,会比蓝牙更好。使用蓝牙方式,不管你用什么协议,都会对数据重新编码,说人话就是有损音质,虽然不至于全损。而使用 Wifi 就可以将 PCM 数据直接传输,无需再编码和压缩。在 ESP32 开发板上可以通过 I2S(IIS)向功放芯片发出音频数据。 关于 i2s 的时序,老

用STM32F4的DMA实现高速、实时的同步并行通信——以读取高速ADC为例[原创www.cnblogs.com/helesheng]

本文给出了一种利用STM32F4系列MCU的DMA功能,实现10MSPS数量级的同步并行数据通信的方法。并用控制高速流水线型的模数转换器AD9200读取作为实例,展示了该通行方法。本文最后总结了该方法的优点和问题,以及克服这些问题的思路。

用python用户注册和短信验证码逻辑实现案例

一.写代码前分析(逻辑分析OK了才可以顺利成章的敲代码): A、用户发送请求 1、注册账号(用户名不能重复)--按照需求进行判断 2、短信验证码(有效期5分钟)--对短信验证码进行保存 B、用户注册、短信验证用不同得函数封装实现 d_user={} #存放用户名和密码的数据字典 verificati

用 VS Code 搞 Qt6:让信号和槽自动建立连接

Qt 具备让某个对象的信号与符合要求的槽函数自动建立连接。弄起来也很简单,只要调用这个静态方法即可: QMetaObject::connectSlotsByName(...); connectSlotsByName 方法需要一个参数,此参数的指针指向一个实例,这个实例自身的信号,以及它的子级对象的信