关于一次程序应用,内存持续升高。排查以及解决方案。

关于一次程序应用,内存持续升高。排查以及解决方案。

一、背景:

关于一次程序应用,内存持续升高。排查以及解决方案。_第1张图片 发现该程序的内存持续增长,无法释放,直到程序关闭/重启后才能释放。否则内存越来越高导致程序处理越来越慢。

二、分析排查

要解决内存持续增长的问题,首先需要定位问题,才能做相应的修复。对于逻辑简单的代码,可以简单直接通过排除法来定位问题代码所在,对于错综复杂的代码,就需要耗费一定时间了。
当然除了排除法,还可以借助内存检测工具来快速定位问题代码。对于.net平台,微软提供.net辅助工具CLR Profiler帮助我们的性能测试人员以及研发人员,找到内存没有及时回收,占着内存不释放的方法。

监测客户端程序运行的结果如下:
关于一次程序应用,内存持续升高。排查以及解决方案。_第2张图片

这是事后在测试环境,空业务使用下,检测了一个晚上。发现内存使用率还是稳定上升,即使用GC强行回收也只能回收到300多。
关于一次程序应用,内存持续升高。排查以及解决方案。_第3张图片

看看检测到的内存溢出的分析报告。
经过注释代码方式测试,空业务测试。发现内存还是在涨,注释代码只是影响内存涨的速度

也通过注释代码查到是哪一块问题。发现是公司插件库里面一个插件,链路疯狂继承,反复实例。导致变成动态数组,donet无法对它进行回收:( 这个span串了很多个builder )

关于一次程序应用,内存持续升高。排查以及解决方案。_第4张图片

对话:
A: 难道这个还不能实锤吗
还有其他原因

我: ispan 里面还有问题
不全部是延时队列
其实就是ispan里面有问题,所以延时队列才会也有问题
不能认为以为是延时队列导致的

三、解决方案

1.项目中添加运行时配置文件(CG强制回收配置-临时解决方案):
runtimeconfig.template.json

{
  "runtimeOptions": {
    "configProperties": {
      "System.GC.HeapHardLimit": 419430400,
      "System.GC.Server": false,
      "System.GC.Concurrent": false
    }
  }
}
2.运维配合写了一个脚本,获取内存占比到达80%,重启一下应用(临时解决方案):
#!/bin/bash
mydate=`date +%Y%m%d_%H%M%S`
myhomedir="/dydata/pro_deliveryFoodSendOrderTask"
mylogdir="${myhomedir}/logs"
ps axf -o "pid %cpu" | awk '{if($2>=80.0) print $1}' | while read procid
do
kill -9 $procid
sleep 10
[ ! -d $mylogdir ] && mkdir $mylogdir
cd ${myhomedir}
nohup dotnet ./FoodOrderTask.dll >>${mylogdir}/start_${mydate}.log 2>&1 &
done
3.查到插件库中代码,针对此问题进行修复。

你可能感兴趣的:(.net,c#,内存泄漏,GC,内存持续升高)