记一次 .NET 某外贸ERP 内存暴涨分析
一:背景
1. 讲故事
上周有位朋友找到我,说他的 API 被多次调用后出现了内存暴涨,让我帮忙看下是怎么回事?看样子是有些担心,但也不是特别担心,那既然找到我,就给他分析一下吧。
二:WinDbg 分析
1. 到底是哪里的泄露
这也是我一直在训练营灌输的理念,一定要知道是哪一边的暴涨,否则很可能就南辕北辙了,使用 !address -summary 和 !eeheap -gc 即可。
0:000> !address -summary--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free 315 7df9`dbf15000 ( 125.976 TB) 98.42%
<unknown> 1056 206`130ec000 ( 2.024 TB) 99.99% 1.58%
Image 1262 0`091ee000 ( 145.930 MB) 0.01% 0.00%
Heap 258 0`04c19000 ( 76.098 MB) 0.00% 0.00%
Stack 114 0`02fc0000 ( 47.750 MB) 0.00% 0.00%
Other 9 0`001db000 ( 1.855 MB) 0.00% 0.00%
TEB 38 0`0004c000 ( 304.000 kB) 0.00% 0.00%
PEB 1 0`00001000 ( 4.000 kB) 0.00% 0.00%--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_MAPPED 260 200`01dbf000 ( 2.000 TB) 98.82% 1.56%
MEM_PRIVATE 1216 6`1912e000 ( 24.392 GB) 1.18% 0.02%
MEM_IMAGE 1262 0`091ee000 ( 145.930 MB) 0.01% 0.00%--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE 315 7df9`dbf15000 ( 125.976 TB) 98.42%
MEM_RESERVE 492 205`3abc6000 ( 2.020 TB) 99.82% 1.58%
MEM_COMMIT 2246 0`e9515000 ( 3.646 GB) 0.18% 0.00%
....0:000> !eeheap -gc
Number of GC Heaps: 8
------------------------------
....
------------------------------
GC Allocated Heap Size: Size: 0x74d77d98 (1960279448) bytes.
GC Committed Heap Size: Size: 0xcb7c6000 (3413925888) bytes.
从卦中看,当前提交内存是 3.64G ,托管堆的提交内存是 3.41G,很明显这是一个 托管内存 暴涨,到这里就比较好解决了。
不知道可有朋友注意到了 GC Allocated Heap Size 和 GC Committed Heap Size 相差甚大,高达 1.5G 之多,上次看到这个情况还是 某电厂 的一个 dump,当时还问了下 Maoni ,说是设计如此,既然说到了设计如此,我还看了下 .NET 版本是 .NET5,所以冷不丁的看下来这个程序的.NET版本,输出如下:
0:000> !eeversion
5.0.621.22011 free
5,0,621,22011 @Commit: 478b2f8c0e480665f6c52c95cd57830784dc9560
Server mode with 8 gc heaps
SOS Version: 6.0.5.7301 retail build
我去 .NET5 再现,其实到这里可以这么说, 至少我觉得 .NET5 在这一块还可以再优化优化。
2. 为什么会相距过大
在 电厂 的那个dump中,后来通过非托管分析,发现有大量的统计信息,后来确认是网站上有一段时间的高频导入导出文件造成的暴涨,这句话的意思就是程序曾经出现过短暂的 快进快出,这就意味着有大量短暂的临时对象产生, CLR 为了高效处理,在短暂对象释放后,并没有将内存归还给 操作系统, 而是自己私吞,目的是防未来可能的爆炸性的内存分配,所以你会看到 分配区域 和 提交区域 过大的底层逻辑了。
原理大概就是这么个原理,那这个 ERP 难道也是出现了 快进快出 的现象吗?是不是我们可以挖一下哈,方法就是统计一下 无根对象 占托管堆的一个 百分比,使用 !heapstat -iu 命令。
0:000> !heapstat -iu
Heap Gen0 Gen1 Gen2 LOH POH
Heap0 124129016 105671896 5371520 4063704 795560
Heap1 100102816 109941488 4421800 4719072 452904
Heap2 144913984 105093616 7285888 4325960 1917928
Heap3 125996096 109904696 8612112 4194608 425976
Heap4 124567184 102635432 7450536 3670432 393400
Heap5 122508864 104438848 12821224 4076136 458616
Heap6 124459664 120851840 5901680 6615192 311352
Heap7 131309360 97620536 8585720 8660720 602072
Total 997986984 856158352 60450480 40325824 5357808Free space: Percentage
Heap0 426616 2332200 3032 393520 264 SOH: 1%
Heap1 380752 2403984 1768 131208 320 SOH: 1%
Heap2 484008 2306424 4328 344 616 SOH: 1%
Heap3 436888 2403000 1168 184 24 SOH: 1%
Heap4 446192 2266944 1936 393512 24 SOH: 1%
Heap5 444176 2302824 5232 131440 24 SOH: 1%
Heap6 429048 2648592 9104 884800 24 SOH: 1%
Heap7 441216 2144136 3272 168992 80 SOH: 1%
Total 3488896 18808104 29840 2104000 1376Unrooted objects: Percentage
Heap0 121561744 103338800 56592 3145872 0 SOH: 95%
Heap1 99418536 107524544 19800 4456760 0 SOH: 96%
Heap2 144081016 102786776 36920 4325616 0 SOH: 95%
Heap3 124591744 107491216 23832 4194424 0 SOH: 94%
Heap4 123946896 100368288 10400 3145824 88 SOH: 95%
Heap5 121457024 102135728 24032 3539136 0 SOH: 93%
Heap6 123739008 118202552 2288 5243072 0 SOH: 96%
Heap7 130593408 95460992 736 3539136 0 SOH: 95%
Total 989389376 837308896 174600 31589840 88
从卦中看,当前 Unrooted objects 区域占 SOH 的比率都是在 93% 以上,就是说托管堆上几乎都是 无根对象,这也验证了 快进快出 的现象,接下来的问题就是挖下是什么导致了 快进快出。
3. 什么导致了 快进快出
要找到这个答案需要到托管堆看一下,是否有超出预期的对象分配,使用 !dumpheap -stat 即可。
0:000> !dumpheap -stat
Statistics:MT Count TotalSize Class Name...
00007ff7bf388fa8 1300147 31203528 System.DateTime
00007ff7c04db260 124 32312064 xxx.UDP_Retention[]
00007ff7bfeb2c00 1239416 317290496 xxx.UDP_Retention
00007ff7c00cfe88 12997664 415925248 FreeSql.Internal.Utils+RowInfo
00007ff7bf107a90 21175792 909769558 System.String
Total 40777517 objects
从卦中看: FreeSql.Internal.Utils+RowInfo 高达 1300w ,同时 xxx.UDP_Retention 对象也高达 123w , FreeSql 相信国内很多开发者都知道,是一个数据访问的SDK,很显然这个 ERP 应该从数据库中读取了不少数据, FreeSql 在内部为了做映射生成了非常多的临时对象。
那现在的突破点在哪里呢?就是寻找问题 SQL,找下和类名同名的表名 UDP_Retention 即可,写个脚本查一下就好了,结果发现有不少这样的 sql,输出如下:
SELECT *
FROM (SELECT *FROM UDP_Retention with(nolock)WHERE ID NOT IN (SELECT xxxIdFROM UDP_Retention_Pxxxx with(nolock)) ) a
那这条 sql 会捞出多少数据呢?可以观察下 UDP_Retention[] 即可,然后稍微过滤一下。
0:000> !DumpHeap -mt 00007ff7c04db260 -min 0n1048576Address MT Size
00000244c3b71188 00007ff7c04db260 1048600
00000244c3c711c0 00007ff7c04db260 1048600
00000244d3bd1120 00007ff7c04db260 1048600
00000244e3a710e0 00007ff7c04db260 1048600
00000244e3cb1230 00007ff7c04db260 1048600
00000244f3a11070 00007ff7c04db260 1048600
00000244f3b910e0 00007ff7c04db260 1048600
00000244f3c91118 00007ff7c04db260 1048600
0000024503a91118 00007ff7c04db260 1048600
0000024503b91150 00007ff7c04db260 1048600
0000024513c74250 00007ff7c04db260 1048600
00000245239c90c8 00007ff7c04db260 1048600
0000024523ac9100 00007ff7c04db260 1048600
0000024523de0048 00007ff7c04db260 1048600
0000024523ee0080 00007ff7c04db260 1048600
00000245339d0f68 00007ff7c04db260 1048600
0000024534013668 00007ff7c04db260 1048600 Statistics:MT Count TotalSize Class Name
00007ff7c04db260 17 17826200 xxx.UDP_Retention[]
Total 17 objects0:000> !DumpObj /d 0000024534013668
Name: xxx.UDP_Retention[]
MethodTable: 00007ff7c04db260
EEClass: 00007ff7bf0467c8
Size: 1048600(0x100018) bytes
Array: Rank 1, Number of elements 131072, Type CLASS (Print Array)
Fields:
None
从卦中信息看, 大概有 17 个 13w 的记录,说明这个sql会一次性捞取 10w+ ,用完之后即刻释放,也就表示为什么 SOH 会占用 93% 以上的无根对象。
三:总结
总的来说,这次内存暴涨是因为程序出现了分配的 快进快出 现象导致的,如果你不想管也可以不用管,GC 在下次发兵时会一举歼灭,如果要做优化的话,需要优化下 sql,不要一次性查询出 10w+ 的数据,不过说实话,FreeSql 在映射方面最好也要做些优化,毕竟产生了 1300w 的临时对象,虽然不是它的错。
相关文章:
记一次 .NET 某外贸ERP 内存暴涨分析
一:背景 1. 讲故事 上周有位朋友找到我,说他的 API 被多次调用后出现了内存暴涨,让我帮忙看下是怎么回事?看样子是有些担心,但也不是特别担心,那既然找到我,就给他分析一下吧。 二࿱…...
关于安卓打包生成aar,jar实现(一)
关于安卓打包生成aar,jar方式 背景 在开发的过程中,主项目引入三方功能的方式有很多,主要是以下几个方面: (1)直接引入源代码module(优点:方便修改源码,易于维护&#…...
QString字符串与16进制QByteArray的转化,QByteArray16进制数字组合拼接,Qt16进制与10进制的转化
文章目录 QString转16进制QByteArry16进制QByteArray转QStringQByteArray16进制数拼接Qt16进制与10进制的转化在串口通信中,常常使用QByetArray储存数据,QByteArray可以看成字节数组,每个索引位置储存一个字节也就是8位的数据,可以储存两位16进制数,可以用uint8取其中的数…...
ElasticSearch安装与启动
ElasticSearch安装与启动 【服务端安装】 1.1、下载ES压缩包 目前ElasticSearch最新的版本是7.6.2(截止2020.4.1),我们选择6.8.1版本,建议使用JDK1.8及以上。 ElasticSearch分为Linux和Window版本,基于我们主要学习…...
JavaWeb中Json传参的条件
JavaWeb中我们常用json进行参数传递 对应的注释为RequestBody 但是json传参是有条件的 最主要是你指定的实体类和对应的json参数能否匹配 1.属性和对应的json参数名称对应 2.对应实体类实现了Serializable接口,可以进行序列化和反序列化,这个才是实体类转…...
包装类+初识泛型
目录 1 .包装类 1.1 基本数据类型对应的包装类 1.2.1装箱 1.2.2拆箱 2.初识泛型 2.1什么是泛型 2.2泛型类 2.3裸类型 2.4泛型的上界 2.5泛型方法 1 .包装类 基本数据类型所对应的类类型 在 Java 中,由于基本类型不是继承自 Object ,为了在泛型…...
基于改进的长短期神经网络电池电容预测,基于DBN+LSTM+SVM的电池电容预测
目录 背影 摘要 LSTM的基本定义 LSTM实现的步骤 基于长短期神经网络LSTM的客电池电容预测 完整代码: 基于长短期神经网络LSTM的公交站客流量预测资源-CSDN文库 https://download.csdn.net/download/abc991835105/88184734 效果图 结果分析 展望 参考论文 背影 为增加电动车行…...
Python 2.x 中如何使用pandas模块进行数据分析
Python 2.x 中如何使用pandas模块进行数据分析 概述: 在数据分析和数据处理过程中,pandas是一个非常强大且常用的Python库。它提供了数据结构和数据分析工具,可以实现快速高效的数据处理和分析。本文将介绍如何在Python 2.x中使用pandas进行数据分析&am…...
获取Spring中bean工具类
获取Spring中bean工具类 工具类 package com.geekmice.springbootselfexercise.utils;import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org…...
【实战篇】亿级高并发电商项目(新建 ego_pojo、ego_mapper、ego_api、ego_provider、搭建后台项目 )十五
目录 八、 搭建 Provide 1 新建 ego_pojo 2 新建 ego_mapper 2.1编写 pom.xml 2.2新建配置文件 编辑...
【Plex】FRP内网穿透后 App无法使用问题
能搜索到这个文章的,应该都看过这位同学的分析【Plex】FRP内网穿透后 App无法使用问题_plex frp无效_Fu1co的博客-CSDN博客 这个是必要的过程,但是设置之后仍然app端无法访问,原因是因为网络端口的问题 这个里面的这个公开端口,可…...
[管理与领导-11]:IT基层管理者 - 目标与落实 - 过程管理失控,结果总难达成的问题思考:如何把过程管控做得更好?
目录 前言: 第1章 问题与现象 1.1 总有意想不到的事发生:意外事件 1.2 总有计划变更:意外影响 1.3 总有一错再错,没有复盘、总结与反思,没有流程与改进 第2章 背后的原因 2.1 缺乏及时的过程检查 - 缺乏异常检测…...
用php语言写一个chatgpt3.5模型的例子
当然可以!使用PHP语言调用OpenAI API与ChatGPT-3.5模型进行交互。首先,确保你已经安装了PHP 7.2或更新版本,并具备可用的OpenAI API密钥。 下面是一个基本的PHP示例,展示了如何使用OpenAI API与ChatGPT-3.5模型进行对话ÿ…...
PHP实现保质期计算器
1.php实现保质期计算, 保质期日期可选,天 、月、年 2. laravel示例 /*** 保质期计算器* return void*/public function expirationDateCal(){$produce_date $this->request(produce_date); // 生产日期$warranty_date $this->reques…...
【独立版】新零售社区团购电商系统生鲜水果商城兴盛优选十荟团源码
【独立版】新零售社区团购电商系统生鲜水果商城兴盛优选十荟团源码...
C++系列十:其他-1. Lua
系列文章目录 Lua 系列文章目录前言Lua介绍:参考链接: 基本语法:函数、迭代器table、userdata、模块元素、元方法:协程、文件读写面向对象、垃圾回收 前言 我写这个博客的一个问题?(●’◡’●) 居然是 取名太难了。 …...
不知道打仗之害,就不知道打仗之利
不知道打仗之害,就不知道打仗之利 【安志强趣讲《孙子兵法》第7讲】 【原文】 夫钝兵挫锐,屈力殚货,则诸侯乘其弊而起,虽有智者,不能善其后矣。 【注释】 屈力殚货:屈力,指力量消耗,…...
【leetcode】242. 有效的字母异位词(easy)
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。 思路: 先比较两字符串长度是否相同,如果不同直接返回false。创建…...
Windows电脑快速搭建FTP服务教程
FTP介绍 FTP(File Transfer Protocol)是一种用于在计算机网络上进行文件传输的标准协议。它提供了一种可靠的、基于客户端-服务器模型的方式来将文件从一个主机传输到另一个主机。在本文中,我将详细介绍FTP的工作原理、数据传输模式以及常见…...
Arduino驱动MQ2模拟烟雾传感器(气体传感器篇)
目录 1、传感器特性 2、硬件原理图 3、控制器和传感器连线图 4、驱动程序 MQ2气体传感器,可以很灵敏的检测到空气中的烟雾、液化气、丁烷、丙烷、甲烷、酒精、氢气等气体,与Arduino结合使用,可以制作火灾烟雾报警、液化气、丁烷、丙烷、甲烷、酒精、氢气气体泄露报警等相…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
