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

记一次 .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 某电力系统 内存暴涨分析

一&#xff1a;背景 1. 讲故事 前些天有位朋友找到我&#xff0c;说他生产上的程序有内存暴涨情况&#xff0c;让我帮忙看下怎么回事&#xff0c;最简单粗暴的方法就是让朋友在内存暴涨的时候抓一个dump下来&#xff0c;看一看大概就知道咋回事了。 二&#xff1a;Windbg 分…...

1.SpringEL初始

SpringEL初始 文章目录 SpringEL初始什么是SpringELSpring BeansSpring EL以XML形式Spring EL以注解形式启用自动组件扫描 执行输出 什么是SpringEL Spring EL与OGNL和JSF EL相似&#xff0c;计算评估或在bean创建时执行。此外&#xff0c;所有的Spring表达式都可以通过XML或注…...

HTTP 状态码

状态码状态码英文名称中文描述100Continue继续。客户端应继续其请求101Switching Protocols切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议&#xff0c;例如&#xff0c;切换到HTTP的新版本协议200OK请求成功。一般用于GET与POST请求201Created已创建。成功…...

ddtrace 系列篇之 dd-trace-java 项目编译

dd-trace-java 是 Datadog 开源的 java APM 框架&#xff0c;本文主要讲解如何编译 dd-trace-java 项目。 环境准备 JDK 编译环境(三个都要&#xff1a;jdk8\jdk11\jdk17) Gradle 8 Maven 3.9 (需要 15G 以上的存储空间存放依赖) Git >2 (低于会出现一想不到的异常&#xf…...

华为aarch64架构的泰山服务器EulerOS 2.0 (SP8)系统离线安装saltstack3003.1实践

华为泰山服务器的CPU芯片架构为aarch64&#xff0c;所装系统为EulerOS 2.0 (SP8)aarch64系统&#xff0c;安装saltstack比较困难。本文讲解通过pip安装方式离线安装saltstack3003.1以进行集中化管理和维护。 一、系统环境 1、操作系统版本 [rootlocalhost ~]# cat /etc/os-r…...

C#中的方法

引言 在C#编程语言中&#xff0c;方法是一种封装了一系列可执行代码的重要构建块。通过方法&#xff0c;我们可以将代码逻辑进行模块化和复用&#xff0c;提高代码的可读性和可维护性。本文将深入探讨C#中的方法的定义、参数传递、返回值、重载、递归等方面的知识&#xff0c;…...

【Flowable】使用UEL整合Springboot从0到1(四)

前言 在前面我们介绍了Springboot简单使用了foleable以及flowableUI的安装和使用&#xff0c;在之前我们分配任务的处理人的时候都是通过Assignee去指定固定的人的。这在实际业务中是不合适的&#xff0c;我们希望在流程中动态的去解析每个节点的处理人&#xff0c;当前flowab…...

WebGL 计算点光源下的漫反射光颜色

目录 点光源光 逐顶点光照&#xff08;插值&#xff09; 示例程序&#xff08;PointLightedCube.js&#xff09; 代码详解 示例效果 逐顶点处理点光源光照效果时出现的不自然现象 更逼真&#xff1a;逐片元光照 示例程序&#xff08;PointLightedCube_perFragment.js…...

Java精品项目源码第61期垃圾分类科普平台(代号V061)

Java精品项目源码第61期垃圾分类科普平台(代号V061) 大家好&#xff0c;小辰今天给大家介绍一个垃圾分类科普平台&#xff0c;演示视频公众号&#xff08;小辰哥的Java&#xff09;对号查询观看即可 文章目录 Java精品项目源码第61期垃圾分类科普平台(代号V061)难度指数&…...

【Unity3D】资源管理

1 前言 Unity 中资源管理方案主要有 Resources、TextAsset、ScriptableObject 、AssetDatabase、PlayerPrefs、Addressables、AssetBundle、SQLite&#xff0c;本文将介绍其中大部分方案。 2 Resources Resources 主要用于加载资源&#xff0c;被加载的资源需要放在 Resources…...

数据结构-----队列

目录 前言 队列 定义 队列的定义和操作方法 队列节点的定义 操作方式 顺序表实现队列&#xff08;C/C代码&#xff09; 链表实现队列&#xff08;C/C代码&#xff09; Python语言实现队列 前言 排队是我们日常生活中必不可少的一件事&#xff0c;去饭堂打饭的时候排队&a…...

postgresql教程

postgreSQL教程目录 postgreSQL 创建数据库的方式&#xff1a;postgreSQL删除数据库的方式&#xff1a;PostgreSQL 创建表格postgre删除表格&#xff1a;postgreSQL INSERT INTO 语句postgreSQL SELECT 语句:postgresql索引&#xff1a;什么情况下要避免使用索引&#xff1f; p…...

1万6千多最好的背单词SQLITE\ACCESS数据库

本来是实在不想再整英语类的数据了&#xff0c;因为实在是太多了&#xff0c;奈何今天弄到的这份数据库实在很精彩&#xff0c;因此还是希望能够有人喜欢。 搞一个“accept”字段的样例&#xff1a; 【explain】 vi. 承认;同意;承兑; vt. 接受;承认;承担;承兑; 【etyma】 ac…...

springboot aop Aspectj 切面

常用&#xff1a; Aspect、Component、Pointcut、Before、AfterReturning SpringBoot的AOP&#xff08;aspect注解&#xff09;的简单使用 - 知乎 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. 代码实现 题目链接&#xff1a;2862. Maximum Element-Sum of a Complete Subset of Indices 1. 解题思路 这一题的核心在于想明白一点&#xff1a; 要使得子序列当中任意两个数之积均为…...

第一百四十七回 自定义组件一

文章目录 概念介绍实现方法示例代码 我们在上一章回中介绍了跟手指移动的小球相关的内容&#xff0c;本章回中将介绍 自定义组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 在项目中有些内容无法通过现有的组件来实现&#xff0c;因此需要自定义组件&#xf…...

MySQL 重复数据的处理

文章目录 MySQL 重复数据的处理一&#xff0c;常用处理方法二&#xff0c;统计重复数据三&#xff0c;过滤重复数据四&#xff0c;删除重复数据拓展&#xff1a;MySQL预防SQL注入&#xff08;一&#xff09;SQL注入 概述&#xff08;二&#xff09;预防措施 MySQL 重复数据的处…...

Java文字描边效果实现

效果&#xff1a; FontUtil工具类的完整代码如下&#xff1a; 其中实现描边效果的函数为&#xff1a;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_…...

农民朋友有福利啦!建行江门市分行“裕农通+农资结算”平台正式上线

随着广东广圣农业发展有限公司办公室内的裕农通“智慧眼”结算机“叮”的一声到账提醒&#xff0c;标志着全国首个“裕农通农资结算“平台的成功上线&#xff0c;也标志着建行广东省江门市分行的裕农通业务又迈上了一个新的台阶。 广东广圣农业发展有限公司&#xff08;以下简…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...