.netcore利用perf分析高cpu使用率
教程:官方文档 https://docs.microsoft.com/zh-cn/dotnet/core/diagnostics/debug-highcpu?tabs=linux
环境:Linux、Docker、.NET Core 3.1 SDK及更高版本
示例代码:https://github.com/dotnet/samples/tree/master/core/diagnostics/DiagnosticScenarios
利用dotnet-dump分析docker容器内存泄露 跟上篇一样,继续使用官方示例代码演示CPU占用情况。
一 在宿主机运行perf
依旧跟随官网教程的步伐,唯一不同的是,我的示例运行在容器中。
还是跟上一篇的观念一样,当生产环境出现问题时一定要当场把问题样本保存下来用于事后分析。
在宿主机中安装好perf工具,然后捕获容器内占用过高的dotnet进程,最后生成火焰图,整个过程一气呵成非常简单;但问题就出现在生成的火焰图根本不显示JIT生成的函数,只显示perf-PID.map,如下图
问题的原因可能是:捕获进程时无法生成CPU地址和JIT生成函数的映射文件,生成火焰图时找不到待分析进程所依赖的库。
接下来,依然本着不污染宿主机的原则,选择在容器内完成一切工作。
二 容器内安装perf
1,重新构建镜像
修改Dockerfile,在原先的基础上加上一个环境变量COMPlus_PerfMapEnabled=1,它的作用是使.NET Core应用在/tmp目录中有权限创建map文件,perf使用此map文件按名称将CPU地址映射到JIT生成的函数。
进入到容器执行export COMPlus_PerfMapEnabled=1,然后perf是无法创建map文件的,所以我们必须在启动容器时就要加上。
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
COPY bin/Release/netcoreapp3.1 .
ENV COMPlus_PerfMapEnabled=1
ENTRYPOINT ["dotnet", "DiagnosticScenarios.dll"]
修改完保存之后,构建镜像,启动容器
[root@localhost Diagnostic_scenarios_sample_debug_target]# docker build -t dumptest .
Sending build context to Docker daemon 1.47MB
...
Successfully tagged dumptest:latest
[root@localhost Diagnostic_scenarios_sample_debug_target]# docker rm -f diagnostic
diagnostic
[root@localhost Diagnostic_scenarios_sample_debug_target]# docker run --name diagnostic --privileged=true -p 888:80 -d dumptest
d2a7037858ed6af0676990bc56ae2b73519c3a8c073db06af639ef30d9588628
2,下载火焰图生成脚本
进入容器之前,可以先做一个准备工作,将生成火焰图需要用到的pl脚本先clone到宿主机(以后会反复用到),当然这一步也可以到容器内操作。
[root@localhost ~]# cd ~
[root@localhost ~]# git clone --depth=1 https://github.com/BrendanGregg/FlameGraph
Cloning into 'FlameGraph'...
Resolving deltas: 100% (61/61), done.
[root@localhost ~]# ls
Diagnostic_scenarios_sample_debug_target FlameGraph
又get到新的知识点git clone --depth=1
加了个--depth=1的好处就是限制clone的深度,不会下载git协作的历史记录,这样可以大大加快克隆的速度。
接下来把FlameGraph拷贝到容器内,然后进入容器:
[root@localhost ~]# docker cp FlameGraph diagnostic:/app/FlameGraph
[root@localhost ~]# docker exec -it diagnostic bash
root@822a953f9f53:/app# ls
DiagnosticScenarios DiagnosticScenarios.dll DiagnosticScenarios.runtimeconfig.dev.json FlameGraph Microsoft.AspNetCore.Mvc.NewtonsoftJson.dll Newtonsoft.Json.dll appsettings.Development.json
DiagnosticScenarios.deps.json DiagnosticScenarios.pdb DiagnosticScenarios.runtimeconfig.json Microsoft.AspNetCore.JsonPatch.dll Newtonsoft.Json.Bson.dll Properties appsettings.json
3,安装linux-perf
root@822a953f9f53:/app# apt update && apt install -y linux-perf vim
...
root@822a953f9f53:/app# perf --version
/usr/bin/perf: line 13: exec: perf_3.10: not found
E: linux-tools-3.10 is not installed.
安装成功后查看perf版本会提示perf_3.10: not found和linux-tools-3.10 is not installed。
被linux-tools
误导,一顿抓瞎折腾半天之后,找遍全网没有任何有用的信息。
索性回到perf本身看看/usr/bin/perf第13行到底是个啥,结果发现好像是内核版本和perf不匹配的原因,uname -r
得到的结果是Linux 3.10...
然而在/usr/bin目录下并没有找到perf_3.10只有perf_4.19,直接把下图中的perf_$version替换成perf_4.19。
root@822a953f9f53:/app# vi /usr/bin/perf
root@822a953f9f53:/usr/bin# perf --version
perf version 4.19.160
三 CPU占用分析
1,perf record
捕获进程
先运行能引发高CPU的链接60000ms, http://192.168.0.161:888/api/diagscenario/highcpu/60000
然后在CPU飙升期间执行perf record捕获进程,容器里面只运行了一个应用,所以进程id为1,这里就不在查找了。
root@1834a15133ed:/app# perf record -p 1 -g -- sleep 20
[ perf record: Woken up 72 times to write data ]
[ perf record: Captured and wrote 17.330 MB perf.data (80022 samples) ]
root@1834a15133ed:/app# ls
DiagnosticScenarios DiagnosticScenarios.pdb FlameGraph Newtonsoft.Json.Bson.dll appsettings.Development.json
DiagnosticScenarios.deps.json DiagnosticScenarios.runtimeconfig.dev.json Microsoft.AspNetCore.JsonPatch.dll Newtonsoft.Json.dll appsettings.json
DiagnosticScenarios.dll DiagnosticScenarios.runtimeconfig.json Microsoft.AspNetCore.Mvc.NewtonsoftJson.dll Properties perf.data
捕获完成之后会在当前目录下生成一个perf.data
文件,在/tmp目录下生成perf-PID.map
和perfinfo-PID.map
文件。
root@d2a7037858ed:/app# cd /tmp
root@d2a7037858ed:/tmp# ls
clr-debug-pipe-1-32163779-in clr-debug-pipe-1-32163779-out dotnet-diagnostic-1-32163779-socket perf-1.map perfinfo-1.map
2,生成火焰图
之前cp到/app目录下的FlameGraph
项目在此刻派上用场。
root@d2a7037858ed:/tmp# cd /app
root@d2a7037858ed:/app# perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flamegraph.svg
...
root@d2a7037858ed:/app# ls
DiagnosticScenarios DiagnosticScenarios.pdb FlameGraph Newtonsoft.Json.Bson.dll appsettings.Development.json perf.data
DiagnosticScenarios.deps.json DiagnosticScenarios.runtimeconfig.dev.json Microsoft.AspNetCore.JsonPatch.dll Newtonsoft.Json.dll appsettings.json
DiagnosticScenarios.dll DiagnosticScenarios.runtimeconfig.json Microsoft.AspNetCore.Mvc.NewtonsoftJson.dll Properties flamegraph.svg
生成完之后取出flamegraph.svg
文件,到浏览器打开。
找到了这个又高又宽的“大平顶”,是由highcpu
这个Action导致。
关于如何看懂火焰图,可以自行百度,底部参考也有给出基础教程链接。
示例项目中就这一个方法在运行,所在找起来非常简单。
实际项目中如果业务复杂、函数多、调用链深话,打开图就是一片密密麻麻。
参考:
Linux性能优化实战学习笔记:第十七讲 https://www.cnblogs.com/luoahong/p/10833689.html
如何读懂火焰图? - 阮一峰的网络日志 http://www.ruanyifeng.com/blog/2017/09/flame-graph.html
.netcore利用perf分析高cpu使用率的更多相关文章
- 如何定位死循环或高CPU使用率(linux)
如何定位死循环或高CPU使用率(linux) 确定是CPU过高 使用top观察是否存在CPU使用率过高现象 找出线程 对CPU使用率过高的进程的所有线程进行排序 ps H -e -o pid,tid ...
- 嵌入式 如何定位死循环或高CPU使用率(linux) 及性能优化
嵌入式 如何定位死循环或高CPU使用率(linux) ln -s /mnt/nfs/_install/usr/bin/sort /usr/bin/sort awk '{print $1,$2,$14, ...
- windebug分析高cpu问题
分析高CPU的关键是找到哪个线程是持续运行,占用CPU时间. 可以隔上两分钟连续抓两个dump文件,使用 !runaway 查看线程运行的时间 通过对比两个dump文件的线程时间,看看哪个线程运行的时 ...
- 嵌入式 如何定位死循环或高CPU使用率(linux)
如何定位死循环或高CPU使用率(linux) 确定是CPU过高 使用top观察是否存在CPU使用率过高现象 找出线程 对CPU使用率过高的进程的所有线程进行排序 ps H -e -o pid,tid ...
- [Java] HashMap 导致的高 CPU 使用率
今天在生产环境遇到一个问题,Java 应用程序的 cpu 使用比例很高,导致整台机器的 cpu 使用率高达 90% ,正常情况下是 20% 左右. 把 Thread dump 导出来,利用 IBM T ...
- 制造高CPU使用率的简单方法
在群里有人问制造CPU占用率高的场景用来做测试.所谓做好事难,干“坏”事还不容易?这个需求有很多方法可以实现,比如使用一些压力测试工具.我首先想 到的是HASH JOIN.这个联接比较消耗CPU资源, ...
- 06 案例篇:系统的 CPU 使用率很高,但为啥却找不到高 CPU 的应用?
上一节我讲了 CPU 使用率是什么,并通过一个案例教你使用 top.vmstat.pidstat 等工具,排查高 CPU 使用率的进程,然后再使用 perf top 工具,定位应用内部函数的问题.不过 ...
- 4 系统的 CPU 使用率很高,但为啥却找不到高 CPU的应用?
上一节讲了 CPU 使用率是什么,并通过一个案例教你使用 top.vmstat.pidstat 等工具,排查高 CPU 使用率的进程,然后再使用 perf top 工具,定位应用内部函数的问题.不过就 ...
- 利用dotnet-dump分析docker容器内存泄露
目录 一 运行官方示例 1,Clone代码并编译 2,创建Dockerfile构建镜像 3,启动容器 二 生成dump转储文件 1,制造问题 2,创建dump文件 三 分析dump文件 1,创建一个用 ...
随机推荐
- 团队作业4-Day5
团队作业4-Day5 项目git地址 1. 站立式会议 2. 项目燃尽图 3. 适当的项目截图 4. 代码/文档签入记录(部分) 5. 每人每日总结 吴梓华:补充了样式代码以方便调试. 白军强:顺利完 ...
- Jmeter(三十三) - 从入门到精通 - Jmeter Http协议录制脚本工具-Badboy6(详解教程)
1.简介 今天分享的就是在上一篇文章的基础上来进行讲解和分享:Badboy使用数据源Excel进行脚本参数化.然后在使用读取的参数进行对比断言. 2.具体场景 Badboy录制一个搜索的脚本,并对搜索 ...
- Java中的Reference类使用
Java 2 平台引入了 java.lang.ref 包,这个包下面包含了几个Reference相关的类,Reference相关类将Java中的引用也映射成一个对象,这些类还提供了与垃圾收集器(gar ...
- 2020中国.NET开发者峰会近50场热点技术专题揭秘
简介 / Summary 2014年微软组织并成立.NET基金会,微软在成为主要的开源参与者的道路上又前进了一步.2014年以来已经有众多知名公司加入.NET基金会,微软,Google,AWS三大云厂 ...
- 配置 Spring Batch 批处理失败重试机制
1. 引言 默认情况下,Spring批处理作业在执行过程中出现任何错误都会失败.然而有些时候,为了提高应用程序的弹性,我们就需要处理这类间歇性的故障. 在这篇短文中,我们就来一起探讨 如何在Sprin ...
- 一起看下MySQL的崩溃恢复到底是怎么回事
目录 回顾 思考一个问题 checkponit机制 Checkpoint的种类及触发条件 LSN 推荐阅读 本文稍微有点晦涩.但是看过之后你就能Get到MySQL的崩溃恢复到底是怎么做的! 文章公号 ...
- IE各版本和Windows的关系
- 跨站点请求伪造 - SpringBoot配置CSRF过滤器
1. 跨站点请求伪造 风险:可能会窃取或操纵客户会话和 cookie,它们可能用于模仿合法用户,从而使黑客能够以该用户身份查看或变更用户记录以及执行事务. 原因:应用程序使用的认证方法不充分. ...
- Restful规则及JPA导致内存溢出
HTTP动词 对于资源的具体操作类型,由HTTP动词表示. 常用的HTTP动词有下面五个(括号里是对应的SQL命令). GET(SELECT):从服务器取出资源(一项或多项). POST(CREATE ...
- yii2 设置的缓存无效,返回false,不存在
为了那些因为标题点进来的小伙伴,我直接把问题解决方案写在开头: 问题描述, $cache->add($key,'value',1800);这样设置了值后,后面无论怎么取这个$key,取出来的结果 ...