这是一个Winform程序,用于项目中的定时运算。症状是,运行一段时间后,内存持续上升。如一天内就能够达到300M。
打开.Net Memory Profiler,监控该程序,一段时间后,看到该程序产生了大量的Int32[]与string。
于是跟着这些个Int32数组与字符串乱点,发现引用链还有很多不同的。
为什么这些Int32数组不被回收呢?
打开Windbg,输入如下命令:
0:000> !finalizequeue SyncBlocks to be cleaned up: 0 MTA Interfaces to be released: 0 STA Interfaces to be released: 0 ---------------------------------- generation 0 has 0 finalizable objects (45db4e24->45db4e24) generation 1 has 1 finalizable objects (45db4e20->45db4e24) generation 2 has 217984 finalizable objects (45ce0020->45db4e20) Ready for finalization 1017 objects (45db4e24->45db5e08) Statistics: MT Count TotalSize Class Name ...通通省略 07fec4d4 33 528 System.WeakReference 09d645c8 10 1200 System.Diagnostics.PerformanceCounter 0b15b068 487 5844 System.Reflection.Emit.DynamicResolver+DestroyScout 0961fd18 816 75072 System.Data.SqlClient.SqlDataAdapter 09d61a80 1632 91392 System.Data.SqlClient.SqlConnection 0b158be0 215952 8638080 System.Reflection.Emit.DynamicResolver Total 219002 objects
finalizequeue查看的是可终结队列,只是可终结,但是还未实际终结。
从现在开始,特别留意这个对象,因为这个对象无法回收。还要特别留意被这个对象引用的对象。于是在.Net Memory Profiler中就特别留意了这个引用,原来Int32[]是被DynamicResolver引用了导致没有被回收。
为什么它未回收呢?先不管这个问题,没兴趣,我只想知道它为什么会产生这么多这个对象。而且这个对象还引用了很多其他的东西。
于是在.Net Memory Profiler中狠狠双击DynamicResolver这个对象,得知其调用堆栈如下。
问题出在同事封装的一个dll,改进同事的代码,不要再去调用这个方法。实际上一个很小的改动就搞定了。
在.Net Memory Profiler中,只要确定问题出在哪个方法就OK了。黑色的是自己的代码,而灰色的通常是已封装成.dll的第三方框架。成熟稳定的第三方框架一般不会出问题,我们只需要改进自己的代码就OK了,但是有时dll是同事封装的,这就要留点心眼了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现