在.NET Core 项目部署后,我们往往会遇到内存占用越来越高的问题,但是由于项目部署在Linux上,因此无法使用VS的远程调试工具来排查内存占用问题。那么这篇文章我们大家一起来学习一下如何排查内存占用问题。
首先,我们来看一下应用部署的环境:
操作系统 | .NET Core版本 |
---|---|
Ubuntu 24.04 | 6.0 |
接下来,我们把调试环境配置好。需要安装两个软件:dotnet-counters 和 dotnet-dump。在控制台输入如下命令:
dotnet tool install --global dotnet-counters
dotnet tool install --global dotnet-dump
dotnet-counters 是一个性能监视工具,用于应用运行状况监视以及简单的性能问题排查。 它可以快速监视 CPU 的使用情况以及 .NET Core 应用程序中引发的异常率。
dotnet-dump 它可以在不调试器代码的情况下收集和分析 操作系统 转储的方法。
一、分析问题
首先,需要获取到应用的进程 pid,然后在控制台输入如下命令:
dotnet-counters monitor -p 进程pid
我们会看到命令行出现了如下信息:
这些信息展示了内存和CPU的实时使用率,其中有4行信息比较重要:Gen 0 Size (B)、Gen 1 Size (B)、Gen 2 Size (B)以及LOH Size (B)。这四行信息分别表示GC 0代、GC 1代、GC 2代以及大型对象堆所占用的内存大小。
在上图中我们发现 LOH 所占用的内存是最多的,那么我们就需要分析一下 LOH 内部到底在做什么。分析前,我们需要获取应用进程的dump文件,在控制台输入如下命令:
dotnet-dump collect -p 进程pid
这时dotnet-dump 会为我们生成一个dump文件(如下述所示),我们利用这个文件就可以分析了。
输入如下命令进入分析界面并查看LOH所做全部操作,如下图所示:
// 进入分析界面
dotnet-dump analyze dump文件名
// 打印LOH所作的全部操作
dg LOH
从打印出来的信息中发现,占用内存最多的就是 rediis,那么我们就来看一下它做了什么,输入如下命令:
dumpheap -mt MT的id
在控制台中打印出了 redis 所作的所有操作,如下图所示:
我们使用 `do`` 命令来看一下它具体做了哪些操作,结果如下所示:
do Address id
从输出内容中,我们发现是StackExchange.Redis 中的值类型占用了较大的内存,后续的步骤就是排查和redis操作相关的代码了。