当前位置: 首页 > news >正文

记一次 .NET 某低代码开发框架 内存暴涨分析

一:背景

1. 讲故事

微信里有一位朋友找到我,说他们公司的程序存在内存暴涨问题,自己分析了下没有找到原因,让我看下怎么回事?由于大家都有dump分析基础,所以交流互通上还是很顺利的,接下来就是上dump分析啦。

二:内存暴涨分析

1. 为什么会内存暴涨

先还是老套路,用 !address -summary 观察下内存分布情况,输出如下:


0:000> !address -summary--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free                                    363     7dfd`e87c7000 ( 125.992 TB)           98.43%
<unknown>                              9276      201`e5858000 (   2.007 TB)  99.96%    1.57%
Heap                                     65        0`2547f000 ( 596.496 MB)   0.03%    0.00%
Image                                  1855        0`09d35000 ( 157.207 MB)   0.01%    0.00%
Stack                                    93        0`02c00000 (  44.000 MB)   0.00%    0.00%
Other                                     9        0`001de000 (   1.867 MB)   0.00%    0.00%
TEB                                      31        0`0003e000 ( 248.000 kB)   0.00%    0.00%
PEB                                       1        0`00001000 (   4.000 kB)   0.00%    0.00%--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE                                363     7dfd`e87c7000 ( 125.992 TB)           98.43%
MEM_RESERVE                             690      201`2b6d4000 (   2.005 TB)  99.82%    1.57%
MEM_COMMIT                            10640        0`ec155000 (   3.689 GB)   0.18%    0.00%

从卦中可以看到,总计 3.6G 的总提交内存,看样子都落到了 Unk 区域,最好是托管层吃掉了,否则就麻烦了,接下来使用 !dumpheap -stat 观察,输出如下:


0:000> !dumpheap -stat
Statistics:MT      Count     TotalSize Class Name
...
0179c7715cb0  1,847,901   451,265,880 Free
7ffc6e0a2888          2   536,870,960 System.WeakReference<Microsoft.Extensions.DependencyInjection.ServiceProvider>[]
7ffc6e0a2260 60,873,978 1,460,975,472 System.WeakReference<Microsoft.Extensions.DependencyInjection.ServiceProvider>
Total 63,333,893 objects, 2,494,520,292 bytes

从卦中可以看到程序中有 6087w 个弱引用,接下来使用 !dumpheap -mt 7ffc6e0a2260 观察下列表详情,然后用 !gcroot 观察其引用根,参考如下:


0:000> !dumpheap -mt 7ffc6e0a2260Address               MT           Size017988001000     7ffc6e0a2260             24 017988001018     7ffc6e0a2260             24 017988001030     7ffc6e0a2260             24 017988001048     7ffc6e0a2260             24 017988001060     7ffc6e0a2260             24 017988001078     7ffc6e0a2260             24 017988001090     7ffc6e0a2260             24 0179880010a8     7ffc6e0a2260             24 ...017a405f1020     7ffc6e0a2260             24 0:000> !gcroot   0179880010a8  
Caching GC roots, this may take a while.
Subsequent runs of this command will be faster.

等了20多分钟都没有出来结果,可能 6kw 的根纵横交错让windbg不堪重负,没有就没撤了,使用内存搜索法寻找上级所属对象。这里就选择 017a405f1020 对象来开刀。

0:000> !dumpobj /d 17a405f1020
Name:        System.WeakReference`1[[Microsoft.Extensions.DependencyInjection.ServiceProvider, Microsoft.Extensions.DependencyInjection]][]
MethodTable: 00007ffc6e0a2888
EEClass:     00007ffc6dbeb4f8
Tracked Type: false
Size:        536870936(0x20000018) bytes
Array:       Rank 1, Number of elements 67108864, Type CLASS (Print Array)
Fields:
None0:000> s-q 0 L?0xffffffffffffffff 17a405f1020
00000179`c95861d0  0000017a`405f1020 03a0dcfa`03a0dcfa0:000> !lno 0000017a`405f1020
Before:       017a405f1000 32 (0x20)                        Free
Current:      017a405f1020 24 (0x18)                        System.WeakReference<Microsoft.Extensions.DependencyInjection.ServiceProvider>[]
Error Detected: Object 17a405f1020 has a bad member at offset 12054c00: ??? [verify heap]
Could not find object after 17a405f1020
Heap local consistency not confirmed.0:000> !lno 00000179`c95861d0
Before:       0179c95861c8 32 (0x20)                        System.Collections.Generic.List<System.WeakReference<Microsoft.Extensions.DependencyInjection.ServiceProvider>>
Next:         0179c95861e8 24 (0x18)                        System.WeakReference<Microsoft.Extensions.DependencyInjection.ServiceProvider>[]
Heap local consistency confirmed.0:000> !dumpobj /d 179c95861c8
Name:        System.Collections.Generic.List`1[[System.WeakReference`1[[Microsoft.Extensions.DependencyInjection.ServiceProvider, Microsoft.Extensions.DependencyInjection]], System.Private.CoreLib]]
MethodTable: 00007ffc6e0a2340
EEClass:     00007ffc6dce0000
Tracked Type: false
Size:        32(0x20) bytes
File:        D:\xxx\A_api\System.Private.CoreLib.dll
Fields:MT    Field   Offset                 Type VT     Attr            Value Name
00007ffc6de328f0  400209f        8     System.__Canon[]  0 instance 0000017a405f1020 _items
00007ffc6dc894b0  40020a0       10         System.Int32  1 instance         60873978 _size
00007ffc6dc894b0  40020a1       14         System.Int32  1 instance         60873978 _version
00007ffc6de328f0  40020a2        8     System.__Canon[]  0   static dynamic statics NYI                 s_emptyArray0:000> s-q 0 L?0xffffffffffffffff 179c95861c8
00000179`c77571d8  00000179`c95861c8 00000000`00000000
00000179`c95861b8  00000179`c95861c8 0800004e`000000000:000> !lno 00000179`c77571d8
Failed to find the segment of the managed heap where the object 179c77571d8 resides0:000> !lno 00000179`c95861b8
Before:       0179c9586108 192 (0xc0)                       Microsoft.Extensions.DependencyInjection.DependencyInjectionEventSource
Next:         0179c95861c8 32 (0x20)                        System.Collections.Generic.List<System.WeakReference<Microsoft.Extensions.DependencyInjection.ServiceProvider>>
Heap local consistency confirmed.

根据卦中的图和输出,终于找到了原来是 DependencyInjectionEventSource._providers 承担了所有,接下来的关注点就来到了 DependencyInjectionEventSource

2. xxxEventSource 是什么

从名字上看和 ETW 事件有关,接下来用 !eeversion 观察 .net 版本,寻找其对应的C#源代码。


0:000> !eeversion
6.0.3624.51421 free
6,0,3624,51421 @Commit: f1dd57165bfd91875761329ac3a8b17f6606ad18
Workstation mode
SOS Version: 9.0.13.2701 retail build

从上面的源代码看,其实也看不出来个所以,毕竟底层的架构我不熟悉,本着我不是第一个吃螃蟹的人,所以拿关键词在网上索一下,果然 stephentoub 大佬在去年4月份就发现了这个问题,在 .net10 中做了修复,看描述是一个优化级的bug,官方链接:https://github.com/dotnet/runtime/issues/114599 截图如下:

修改后的代码如下,果然加了很多的业务逻辑来处理。

[NonEvent]public void ServiceProviderBuilt(ServiceProvider provider){lock (_providers){int providersCount = _providers.Count;if (providersCount > 0 &&(_survivingProvidersCount is int spc ? (uint)providersCount >= 2 * (uint)spc : providersCount == _providers.Capacity)){_providers.RemoveAll(static p => !p.TryGetTarget(out _));_survivingProvidersCount = _providers.Count;}_providers.Add(new WeakReference<ServiceProvider>(provider));}WriteServiceProviderBuilt(provider);}

从官方描述来看,就是有人创建了 scope,但后续没有调用 dispose 方法来及时释放,导致框架中的 WeakReference 引用滞留,引发内存暴涨,可以说两者都有责任吧。

解决办法很简单,两种方式:

  1. 检查代码里写 BuildServiceProvider 的地方没有即时的 Dispose。
  2. 升级到 .NET10 ,这是最简单粗暴的方法。

把结论告诉朋友后,朋友终于在2天后给我反馈了好消息,好心情溢于言表!

三:总结

dump之旅是一个修理工不断自我修炼的过程,必须学会在绝望中寻找希望的能力。

图片名称
http://www.jsqmd.com/news/453178/

相关文章:

  • kde nero启动后提示检测到设置了 GTK_IM_MODULE 和 QT_IM_MODULE
  • 2026年湖南专业家装公司价格大揭秘,旧房翻新费用多少钱 - 工业品网
  • 聊聊2026年预制直埋保温管性价比高的供应商排名,集中供热必备 - 工业设备
  • 2026年广州口碑不错的360航空软包汽车脚垫供应商,哪家值得选 - 工业品牌热点
  • 2026年 南通崇川区异宠医院推荐榜:环境优越、专业诊疗与暖心服务的口碑之选 - 品牌企业推荐师(官方)
  • 聊聊福安客厅沙发优质供应商,哪家品牌值得推荐? - mypinpai
  • 总结2026年厦门高压发电机出租排名前十的公司 - 工业品网
  • 2026年松筒线生产厂推荐,靠谱的品牌有哪些? - myqiye
  • 2026年高强缝纫线耐磨厂家哪家性价比高,中祥线业实力揭秘 - 工业推荐榜
  • 2026年聊聊全国靠谱的螺杆泵认证厂家,螺杆泵性价比哪家高 - 工业品牌热点
  • 研发测试质量规范(草稿)
  • 2026年泉州性价比高的仿古砖龙头制造商排名,好用品牌大盘点 - mypinpai
  • 中电金信:规范与灵活兼得,让数据模型更“好用”
  • 2026年松筒线制造企业十大排名,松筒线来样定制服务靠谱吗 - myqiye
  • 2026年靠谱的垃圾桶源头厂家有哪些,专业的垃圾桶公司费用多少 - 工业推荐榜
  • 保温管制造企业怎么选,河北宝温管道性价比值得考虑吗 - 工业设备
  • 聊聊杭州地区靠谱的保温管专业制造商,费用怎么收取? - 工业设备
  • 2026年全国小型电动环卫车哪家靠谱?技术成熟 专业服务适配各类需求 - 深度智识库
  • 2026年分析理发器厂商,广州艾渼为何口碑这么好 - 工业品网
  • 2026年评价高的市政护栏厂家推荐:防撞护栏公司口碑推荐 - 行业平台推荐
  • 2026年评价高的护栏厂家推荐:桥梁护栏/临时护栏厂家选择指南 - 行业平台推荐
  • 信息系统项目管理师-归纳
  • AI元人文:空论——指月之间
  • 2026年质量好的阳台护栏工厂推荐:道路护栏/波形护栏源头厂家推荐 - 行业平台推荐
  • 2026畅益家座椅电梯厂家一手直销口碑好吗,靠谱品牌推荐 - mypinpai
  • 2026黄浦区静安区风貌别墅装修公司推荐 老洋房改造+工装全案装修公司推荐 - 品牌智鉴榜
  • 电力电缆、电线电缆、控制电缆厂家哪家好?华科中缆以实力领跑电线电缆行业 - 深度智识库
  • 2026年1月市面上评价优良的蘑菇石厂家排行分析,蘑菇石/碎拼石/贴墙石/脚踏石/地铺石/石材,蘑菇石供应商推荐排行榜单 - 品牌推荐师
  • 分析东云助创团队专业度高吗,在北上广服务性价比如何? - myqiye
  • 2026江苏考研直营机构盘点:五家实力品牌深度解析 - 2026年企业推荐榜