记一次 .NET 某电力系统 内存暴涨分析
一:背景
1. 讲故事
前些天有位朋友找到我,说他生产上的程序有内存暴涨情况,让我帮忙看下怎么回事,最简单粗暴的方法就是让朋友在内存暴涨的时候抓一个dump下来,看一看大概就知道咋回事了。
二:Windbg 分析
1. 到底是谁吃了内存
这个问题说的再多也不为过,一定要看清楚这个程序是如何个性化发展的,可以使用 !address -summary
命令。
0:000> !address -summary--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free 255 7dfb`064e1000 ( 125.981 TB) 98.42%
<unknown> 529 204`d53ac000 ( 2.019 TB) 99.97% 1.58%
Heap 889 0`170f0000 ( 368.938 MB) 0.02% 0.00%
Image 1214 0`07a9a000 ( 122.602 MB) 0.01% 0.00%
Stack 192 0`05980000 ( 89.500 MB) 0.00% 0.00%
Other 10 0`001d8000 ( 1.844 MB) 0.00% 0.00%
TEB 64 0`00080000 ( 512.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 255 7dfb`064e1000 ( 125.981 TB) 98.42%
MEM_RESERVE 709 204`43eab000 ( 2.017 TB) 99.86% 1.58%
MEM_COMMIT 2190 0`b5c64000 ( 2.840 GB) 0.14% 0.00%
从卦象看进程内存也才 2.84G
,严格来说也不算多,可能朋友抓的有点心急,从上面的 unknown
指标看大概率是托管堆的暴涨,继续使用 !eeheap -gc
观察下托管堆。
0:000> !eeheap -gc========================================
Number of GC Heaps: 4
----------------------------------------
Heap 0 (000001d0adf50a20)
generation 0 starts at 1d0b3fad350
generation 1 starts at 1d0b3f9be88
generation 2 starts at 1d0ae5d1000
ephemeral segment allocation context: none
Small object heapsegment begin allocated committed allocated size committed size 01d0ae5d0000 01d0ae5d1000 01d0b4046258 01d0b48ac000 0x5a75258 (94851672) 0x62dc000 (103661568)
Large object heap starts at 1d4ae5d1000segment begin allocated committed allocated size committed size 01d4ae5d0000 01d4ae5d1000 01d4b6d0c4e8 01d4b6d2d000 0x873b4e8 (141800680) 0x875d000 (141938688)
Pinned object heap starts at 1d4ee5d1000segment begin allocated committed allocated size committed size 01d4ee5d0000 01d4ee5d1000 01d4ee5e4f08 01d4ee5f2000 0x13f08 (81672) 0x22000 (139264)
------------------------------
...
Heap 3 (000001d0ae4fd000)
generation 0 starts at 1d3b26929e0
generation 1 starts at 1d3b2687ad8
generation 2 starts at 1d3ae5d1000
ephemeral segment allocation context: none
Small object heapsegment begin allocated committed allocated size committed size 01d3ae5d0000 01d3ae5d1000 01d4179a5980 01d418021000 0x693d4980 (1765624192) 0x69a51000 (1772425216)
Large object heap starts at 1d4de5d1000segment begin allocated committed allocated size committed size 01d4de5d0000 01d4de5d1000 01d4df8836d8 01d4df884000 0x12b26d8 (19605208) 0x12b4000 (19611648)
Pinned object heap starts at 1d51e5d1000segment begin allocated committed allocated size committed size 01d51e5d0000 01d51e5d1000 01d51e5dd7e0 01d51e5e2000 0xc7e0 (51168) 0x12000 (73728)
------------------------------
GC Allocated Heap Size: Size: 0x8a6b9060 (2322305120) bytes.
GC Committed Heap Size: Size: 0x8c6b1000 (2355826688) bytes.
从GC堆看果然是托管层的问题,继续使用 !dumpheap -stat
观察下托管堆的现状,看看哪一位是罪魁祸首。
0:000> !dumpheap -stat
Statistics:MT Count TotalSize Class Name
...
7fff32e81db8 43 68,801,032 SmartMeter.Mem.TerminalInfo[]
7fff329f7470 200,000 110,400,000 SmartMeter.Model.MeterInfo_Model
7fff3227d708 2,285,392 116,193,998 System.String
01d0ae46b350 543 1,857,281,320 Free
Total 3,947,969 objects, 2,314,533,332 bytesFragmented blocks larger than 0.5 MB:Address Size Followed By01d0ae935870 723,384 01d0ae9e6228 System.SByte[]01d1b41d3cd0 23,081,616 01d1b57d6f60 System.Byte[]01d3b274eb40 1,696,943,656 01d4179a3968 System.Byte[]
这卦不看不知道,一看吓一跳,这2.3G
的内存,居然被一个 1.69G
的Free给侵吞了,不信的话可以用 !do
验证下。
0:000> !do 01d3b274eb40
Free Object
Size: 1696943656(0x65254e28) bytes
2. 为什么会有这么大的Free
这是一个值得思考的问题,也决定着我们下一步分析的方向,接下来就是看下这个 free 的落脚点以及周围对象的分布情况,可以使用 !gcwhere
观察。
0:000> !gcwhere 01d3b274eb40
Address Heap Segment Generation Allocated Committed Reserved
01d3b274eb40 3 01d3ae5d0000 0 1d3ae5d1000-1d4179a5980 1d3ae5d0000-1d418021000 1d418021000-1d4ae5d00000:000> !dumpheap -segment 1d3ae5d0000...01d3b274e948 7fff32468658 96 01d3b274e9a8 7fff3227d708 28 01d3b274e9c8 7fff3227d708 28 01d3b274e9e8 7fff32d0c8d8 80 01d3b274ea38 7fff3227d708 96 01d3b274ea98 7fff32d0aa38 40 01d3b274eac0 01d0ae46b350 128 Free01d3b274eb40 01d0ae46b350 1,696,943,656 Free01d4179a3968 7fff323e1638 8,216
从卦象看挺遗憾的,如果 Free 落在segment的最后一个位置,那么 segment 就会 uncommitted 进而内存就下去了,可偏偏最后一个位置是 8216byte 的对象占据着,阻止了内存的回收,有经验的朋友可能知道,这个对象非富即贵,大概率是被 pinned 了,可以用 !gcroot
观察下。
0:000> !gcroot 01d4179a3968
HandleTable:000001d0ae3927f8 (async pinned handle)-> 01d3b26706f0 System.Threading.OverlappedData -> 01d4179a3968 System.Byte[] Found 1 unique roots.0:000> !dumpobj /d 1d4179a3968
Name: System.Byte[]
MethodTable: 00007fff323e1638
EEClass: 00007fff323e15b8
Tracked Type: false
Size: 8216(0x2018) bytes
Array: Rank 1, Number of elements 8192, Type Byte (Print Array)
Content: ............L.o.g.\.2.0.2.3.0...
Fields:
None
从上面的 async pinned handle
来看是一个文件监控的回调函数,到这里就可以从表象解释:是这个 8216 的对象导致的内存无法回收。
3. 真的要 8216 来担责吗
如果你真的要让 8216 来担责,那真的只看到了表象,内存的突然暴涨回不去只是恰好遇到了 8216 的阻止,但它不是本质原因,真正要考虑的是为什么GC回收后会产生这么大一个单独 Free,其实隐喻了当前程序出现过短时的 大对象分配
,对,就是这个词。
接下来的问题是如何找到这个 大对象分配
呢? 最好的方法就是用 perfview
的 .NET SampAlloc 去洞察,如果非要用 WinDbg 的话那就只能看看 Free 生前是什么,或许能寻找到答案,可以借助 .writemem
命令观察。
0:000> !do 01d3b274eb40
Free Object
Size: 1696943656(0x65254e28) bytes0:000> .writemem D:\testdump\1.txt 01d3b274eb40 L?0x65254e28
Writing 65254e28 bytes................
从卦中数据看有大量的计费信息,看样子又是从数据库中短时的捞取了大批量数据在托管堆上折腾导致的,知道了本质原因,解决办法就比较简单了,通常有两种做法。
-
修改 GC 模式,改成 Workstation。
-
大批量数据 改成 小步快跑
三:总结
这起内存暴涨事故,表象上是 8216 的阻挡导致了内存无法被uncommitted所致,本质上还是归于托管堆的 内存黑洞
现象。
相关文章:
记一次 .NET 某电力系统 内存暴涨分析
一:背景 1. 讲故事 前些天有位朋友找到我,说他生产上的程序有内存暴涨情况,让我帮忙看下怎么回事,最简单粗暴的方法就是让朋友在内存暴涨的时候抓一个dump下来,看一看大概就知道咋回事了。 二:Windbg 分…...
1.SpringEL初始
SpringEL初始 文章目录 SpringEL初始什么是SpringELSpring BeansSpring EL以XML形式Spring EL以注解形式启用自动组件扫描 执行输出 什么是SpringEL Spring EL与OGNL和JSF EL相似,计算评估或在bean创建时执行。此外,所有的Spring表达式都可以通过XML或注…...
HTTP 状态码
状态码状态码英文名称中文描述100Continue继续。客户端应继续其请求101Switching Protocols切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议200OK请求成功。一般用于GET与POST请求201Created已创建。成功…...
ddtrace 系列篇之 dd-trace-java 项目编译
dd-trace-java 是 Datadog 开源的 java APM 框架,本文主要讲解如何编译 dd-trace-java 项目。 环境准备 JDK 编译环境(三个都要:jdk8\jdk11\jdk17) Gradle 8 Maven 3.9 (需要 15G 以上的存储空间存放依赖) Git >2 (低于会出现一想不到的异常…...
华为aarch64架构的泰山服务器EulerOS 2.0 (SP8)系统离线安装saltstack3003.1实践
华为泰山服务器的CPU芯片架构为aarch64,所装系统为EulerOS 2.0 (SP8)aarch64系统,安装saltstack比较困难。本文讲解通过pip安装方式离线安装saltstack3003.1以进行集中化管理和维护。 一、系统环境 1、操作系统版本 [rootlocalhost ~]# cat /etc/os-r…...
C#中的方法
引言 在C#编程语言中,方法是一种封装了一系列可执行代码的重要构建块。通过方法,我们可以将代码逻辑进行模块化和复用,提高代码的可读性和可维护性。本文将深入探讨C#中的方法的定义、参数传递、返回值、重载、递归等方面的知识,…...
【Flowable】使用UEL整合Springboot从0到1(四)
前言 在前面我们介绍了Springboot简单使用了foleable以及flowableUI的安装和使用,在之前我们分配任务的处理人的时候都是通过Assignee去指定固定的人的。这在实际业务中是不合适的,我们希望在流程中动态的去解析每个节点的处理人,当前flowab…...
WebGL 计算点光源下的漫反射光颜色
目录 点光源光 逐顶点光照(插值) 示例程序(PointLightedCube.js) 代码详解 示例效果 逐顶点处理点光源光照效果时出现的不自然现象 更逼真:逐片元光照 示例程序(PointLightedCube_perFragment.js…...
Java精品项目源码第61期垃圾分类科普平台(代号V061)
Java精品项目源码第61期垃圾分类科普平台(代号V061) 大家好,小辰今天给大家介绍一个垃圾分类科普平台,演示视频公众号(小辰哥的Java)对号查询观看即可 文章目录 Java精品项目源码第61期垃圾分类科普平台(代号V061)难度指数&…...
【Unity3D】资源管理
1 前言 Unity 中资源管理方案主要有 Resources、TextAsset、ScriptableObject 、AssetDatabase、PlayerPrefs、Addressables、AssetBundle、SQLite,本文将介绍其中大部分方案。 2 Resources Resources 主要用于加载资源,被加载的资源需要放在 Resources…...
数据结构-----队列
目录 前言 队列 定义 队列的定义和操作方法 队列节点的定义 操作方式 顺序表实现队列(C/C代码) 链表实现队列(C/C代码) Python语言实现队列 前言 排队是我们日常生活中必不可少的一件事,去饭堂打饭的时候排队&a…...
postgresql教程
postgreSQL教程目录 postgreSQL 创建数据库的方式:postgreSQL删除数据库的方式:PostgreSQL 创建表格postgre删除表格:postgreSQL INSERT INTO 语句postgreSQL SELECT 语句:postgresql索引:什么情况下要避免使用索引? p…...
1万6千多最好的背单词SQLITE\ACCESS数据库
本来是实在不想再整英语类的数据了,因为实在是太多了,奈何今天弄到的这份数据库实在很精彩,因此还是希望能够有人喜欢。 搞一个“accept”字段的样例: 【explain】 vi. 承认;同意;承兑; vt. 接受;承认;承担;承兑; 【etyma】 ac…...
springboot aop Aspectj 切面
常用: Aspect、Component、Pointcut、Before、AfterReturning SpringBoot的AOP(aspect注解)的简单使用 - 知乎 springboot项目中引入Aspectj并使用_springboot引入aspectj_山鬼谣me的博客-CSDN博客...
Leetcode 2862. Maximum Element-Sum of a Complete Subset of Indices
Leetcode 2862. Maximum Element-Sum of a Complete Subset of Indices 1. 解题思路2. 代码实现 题目链接:2862. Maximum Element-Sum of a Complete Subset of Indices 1. 解题思路 这一题的核心在于想明白一点: 要使得子序列当中任意两个数之积均为…...
第一百四十七回 自定义组件一
文章目录 概念介绍实现方法示例代码 我们在上一章回中介绍了跟手指移动的小球相关的内容,本章回中将介绍 自定义组件.闲话休提,让我们一起Talk Flutter吧。 概念介绍 在项目中有些内容无法通过现有的组件来实现,因此需要自定义组件…...
MySQL 重复数据的处理
文章目录 MySQL 重复数据的处理一,常用处理方法二,统计重复数据三,过滤重复数据四,删除重复数据拓展:MySQL预防SQL注入(一)SQL注入 概述(二)预防措施 MySQL 重复数据的处…...
Java文字描边效果实现
效果: FontUtil工具类的完整代码如下: 其中实现描边效果的函数为:generateAdaptiveStrokeFontImage() package com.ncarzone.data.contentcenter.biz.img.util;import org.springframework.core.io.ClassPathResource; import org.springfr…...
【Web_环境搭建_Python3_pip】pip的升级、安装、更新、卸载,以及pipupgrade和pip-review的基础使用
** 官方说明 ** pip(Python Package Index)是一个以 Python 语言写成的软件包管理系統,使用 pip 可以非常方便的安装和管理 python 软件包PIP ** 查看信息 ** 查看版本 : pip --version查看已有 : pip list、pip freeze查看帮助 : pip help查看库信息 : pip show -f package_…...
农民朋友有福利啦!建行江门市分行“裕农通+农资结算”平台正式上线
随着广东广圣农业发展有限公司办公室内的裕农通“智慧眼”结算机“叮”的一声到账提醒,标志着全国首个“裕农通农资结算“平台的成功上线,也标志着建行广东省江门市分行的裕农通业务又迈上了一个新的台阶。 广东广圣农业发展有限公司(以下简…...
super详解
父类 package com.mypackage.oop.demo06;public class Person06{public Person06() {System.out.println("Person06无参执行了");}protected String name "hexioahei";public void print(){System.out.println("Person");} }子类 package com…...
GMS地下水数值模拟丨GMS各模块、三维地质模型构建及与MODFLOW耦合、地下水流动数值模拟及报告编制、地下水溶质运移模型、反应性溶质运移等
目录 第一部分 地下水数值模拟理论模块 第二部分 地下水数值模拟数据收集、准备及预处理 第三部分 GMS各模块实践 第四部分 三维地质模型构建及与MODFLOW耦合 第五部分 地下水流动数值模拟及报告编制 第六部分 地下水溶质运移模型 第七部分 反应性溶质运移 更多应用 以…...
Redis 配置文件详解 - 持久化(RDB、AOF)
目录 Redis 配置文件详解 单位 包含 INCLUDES 网络 NETWORK 通用 GENERAL 快照 SNAPSHOTTING (持久化) 复制 REPLICATION(主从复制) 安全 SECURITY(账号密码设置) 编辑 限制 CLIENTS 追加模…...
在线Excel转JSON工具
在线Excel转JSON工具 上传excel将数据转换成json格式...
Spring编程常见错误50例-Spring Bean依赖注入常见错误(下)
Value没有注入预期的值 问题 对于Value可以装配多种类型的数据: 装配对象: Value("#{student}") private Student student;Bean public Student student(){Student student createStudent(1, "xie");return student; }装配字符…...
SpringBoot整合Canal实现MySQL与ES数据同步
文章目录 SpringBoot项目引入Canal依赖配置文件项目结构设置监听类其余类、接口内容启动类实体类Controller类Mapper接口Serice接口 运行测试 开始之前请确认docker中已运行mysql与canal容器,并完成了监听binlog配置 未完成可移步: Docker部署Canal监听…...
Zookeeper 源码分析流程
文章目录 前言Zookeeper启动加载磁盘数据与客户端的通信交互Leader选举准备节点状态处理总结 前言 Zookeeper 作为分布式协调服务为分布式系统提供了一些基础服务,如:命名服务、配置管理、同步等,使得开发者可以更加轻松地处理分布式问题。 …...
计数排序与基数排序
计数排序与基数排序 计数排序 计数排序:使用一个数组记录序列中每一个数字出现的次数,将该数组的下标作为实际数据,元素的值作为数据出现的次数。例如对于序列[3,0,1,1,3,3,0,2],统计的结果为: 0出现的次数…...
Mysql—表操作
目录 1、linux中数据库表名区分大小写,windows不区分2、创建数据库表3、外键4、查看数据表结构5、修改表5.1、修改表名5.2、添加字段5.3、指定位置添加字段5.4、修改字段名称5.5、修改字段类型5.6、修改字段位置5.7、删除字段5.8、修改表存储引擎5.9、删除外键 1、l…...
SpringCloud——微服务
微服务技术栈 在之前的开发过程中,我们将所有的服务都部署在一台服务器中,当我们的服务开始越来越多,业务越来越复杂,当一台服务器不能承担我们的业务的时候,就需要将不同的业务分开部署在不同的服务器上,…...
电子商务网站规划设计包括哪些方面/优化大师下载
字符函数 1: ASCII(‘A’) 返回对应ASCII码表中的位置 SELECT ASCII(A) FROM DUAL 效果图如下: 2:concat(‘HELLO’,‘oracle’) 字符串拼接或’HELLO’’,ORACLE’ SELECT CONCAT(Hello,,Oracle) FROM DUAL 效果图如下: 3:LENGTH(‘HE LLO’) 返回…...
广州网站建设o2o/新东方英语培训机构官网
说到文件大小,刚好常有人问我说MySQL是否有单个表的大小限制?限制多大呢?这里做一个简单的介绍吧。 在老版本的MySQL 3.22中,MySQL的单表限大小为4GB,当时的MySQL的存储引擎还是ISAM存储引擎。但是,当出现…...
那家做网站好/上海公布最新情况
中兴路由器无中继的DHCP配置一、实验目的二、实验内容三、实验流程四、实验总结一、实验目的 掌握DHCP的基本原理和作用,及其DHCP的网络架构; 二、实验内容 1.完成路由器DHCP(不含中继)的基本配置和结果验证; 三、…...
网站点击弹出下载框 怎么做/知名做网站的公司
Unity和Maya 今天在美术同事那儿了解些Maya常识,加上自己在Unity3D中的一点儿小操作,记录一下Gizmos 之前就知道Maya和Unity3D的轴向是一致的,在同事那儿看他操作Maya之后,发现这两者在操作上有一些类似。 Unity3D的轴向 有趣的是…...
网站设置首页连接分类页的视频教程/网络营销专业培训学校
在mongo db4.x 中,或mongo db cluser中,如果admin密码忘记了,必须按下面的步骤来做。 思路为注释掉security认证部分,重启mongo server, 重建admin用户,再打开security,重启mongo server,就OK了 on master and slave …...
广西建设官方网站/企业百度推广怎么收费
HTTP事务的剖析 本指南的目的是让你充分了解Node.js HTTP处理的过程,我们假设你在一般意义上知道HTTP请求的工作方式,无论语言或编程环境如何,我们还假设你对Node.js EventEmitters和Streams有点熟悉,如果你对它们不太熟悉&#x…...