記一次 .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?的臨時對象,雖然不是它的錯。?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/40936.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/40936.shtml
英文地址,請注明出處:http://en.pswp.cn/news/40936.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【軟件測試】接口測試工具APIpost

說實話&#xff0c;了解APIpost是因為&#xff0c;我的所有接口相關的文章下&#xff0c;都有該APIpost水軍的評論&#xff0c;無非就是APIpost是中文版的postman&#xff0c;有多么多么好用&#xff0c;雖然咱也還不是什么啥網紅&#xff0c;但是不知會一聲就亂在評論區打廣告…

【力扣每日一題】2023.8.14 合并二叉樹

目錄 題目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代碼&#xff1a; 題目&#xff1a; 示例&#xff1a; 分析&#xff1a; 給我們合并兩棵二叉樹&#xff0c;合并的方式就是把對應位置的節點的值相加&#xff0c;最后把合并后的二叉樹的根節點返回出去。 這類二…

You have docker-compose v1 installed, but we require Docker Compose v2.

curl -SL https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose chmod x /usr/local/bin/docker-compose docker-compose --version

一文看盡R-CNN、Fast R-CNN、Faster R-CNN、YOLO、SSD詳解

一文看盡R-CNN、Fast R-CNN、Faster R-CNN、YOLO、SSD詳解 以下六篇文章總結詳細&#xff1a; 1. 一文讀懂目標檢測&#xff1a;R-CNN、Fast R-CNN、Faster R-CNN、YOLO、SSD 2. 【深度學習】R-CNN 論文解讀及個人理解 3、R-CNN論文詳解 4、一文讀懂Faster RCNN 5、學一百遍都…

JAVA基礎知識(六)——異常處理

異常 一、異常概述與異常體系結構二、常見異常三、異常處理機制一&#xff1a;try-catch-finally四、異常處理機制二&#xff1a;throws五、手動拋出異常&#xff1a;throw六、用戶自定義異常類七、開發中如何選擇使用try-catch-finally還是使用throws八、如何看待代碼中的編譯…

goland插件推薦Rider UI Theme Pack

推薦一個goland配色插件Rider UI Theme Pack&#xff0c;里面自帶visual assist配色&#xff0c;配色截圖如下&#xff1a; 直接在plugins里面進行搜索或者在插件home page下載后進行安裝&#xff0c; 然后按照下圖進行設置即可。 此插件還適用于Jetbrains旗下的Clion和Pycharm…

WX1860- ngbe-1.2.5 xdp程序在路由模式下,使用iperf工具測試數據包不轉發,用jmeter可以

本地驗證時重定向iperf包有出現calltrace錯誤&#xff0c;經推斷&#xff0c;系統PAGE_SIZE<8k時可能出現&#xff08;getconf PAGE_SIZE指令可查看&#xff09;&#xff0c;按下圖將ngbe_main.c的2350行ngbe_rx_bufsz改為ngbe_rx_pg_size可修復。其次&#xff0c;需要將加載…

鴻蒙3.1 基于Token的訪問控制

介紹 代碼路徑:security_access_token: ATM(AccessTokenManager)是OpenHarmony上基于AccessToken構建的統一的應用權限管理能力。 ATM(AccessTokenManager)是OpenHarmony上基于AccessToken構建的統一的應用權限管理能力。 應用的Accesstoken信息主要包括應用身份標識APPID、…

什么是游戲出海運營?

游戲出海運營&#xff0c;也稱為游戲海外運營&#xff0c;是指將原本面向國內市場的游戲產品拓展到國際市場&#xff0c;以在海外地區推廣、發行、運營游戲的過程。這涵蓋了從市場調研、產品適應性優化、本地化翻譯、推廣營銷、社區互動到客戶支持等一系列策略和活動&#xff0…

阿里云對象存儲服務OSS

1、引依賴 <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.15.1</version> </dependency> <dependency><groupId>javax.xml.bind</groupId><artifa…

Mocha and Red and Blue

一、題目 題面翻譯 給定長為 n n n 的僅由 R \texttt{R} R、 B \texttt{B} B、 ? \texttt{?} ? 組成的字符串 S S S&#xff0c;請你在 ? \texttt{?} ? 處填入 R \texttt{R} R 或 B \texttt{B} B&#xff0c;使得相鄰位置字符相同的數量最少。 譯者 ajthreac 題…

Hadoop HA集群兩個NameNode都是standby或者主NameNode是standby,從NameNode是active的情況集錦

文章目錄 背景架構HDFS HA配置錯誤原因解決方案方案一方案二方案三&#xff08;首先查看自己各參數文件是否配置出錯&#xff09; 后記補充failovertransitionToActive 常用端口號及配置文件常用端口號hadoop3.xhadoop2.x 常用配置文件 這里說一下配置Hadoop HA集群可能出現的兩…

Linux多線程【初識線程】

?個人主頁&#xff1a; 北 海 &#x1f389;所屬專欄&#xff1a; Linux學習之旅 &#x1f383;操作環境&#xff1a; CentOS 7.6 阿里云遠程服務器 文章目錄 &#x1f307;前言&#x1f3d9;?正文1、什么是線程&#xff1f;1.1、基本概念1.2、線程理解1.3、進程與線程的關系…

分布式事務與解決方案

一、什么是分布式事務 首先我們知道本地事務是指事務方法中的操作只依賴本地數據庫&#xff0c;可保證事務的ACID特性。而在分布式系統中&#xff0c;一個應用系統被拆分為多個可獨立部署的微服務&#xff0c;在一個微服務的事務方法中&#xff0c;除了依賴本地數據庫外&#…

【深入理解ES6】塊級作用域綁定

1. var聲明及變量提升機制 提升&#xff08;Hoisting&#xff09;機制&#xff1a;通過關鍵字var聲明的變量&#xff0c;都會被當成在當前作用域頂部生命的變量。 function getValue(condition){if(condition){var value "blue";console.log(value);}else{// 此處…

代碼隨想錄算法訓練營第三十六天 | 435. 無重疊區間,763.劃分字母區間,56. 合并區間

代碼隨想錄算法訓練營第三十六天 | 435. 無重疊區間&#xff0c;763.劃分字母區間&#xff0c;56. 合并區間 435. 無重疊區間:eyes:題目總結:eyes: 763.劃分字母區間:eyes:題目總結:eyes: 56. 合并區間:eyes:題目總結:eyes: 435. 無重疊區間 題目鏈接 視頻講解 給定一個區間的…

并發編程系列-Semaphore

Semaphore&#xff0c;如今通常被翻譯為"信號量"&#xff0c;過去也曾被翻譯為"信號燈"&#xff0c;因為類似于現實生活中的紅綠燈&#xff0c;車輛是否能通行取決于是否是綠燈。同樣&#xff0c;在編程世界中&#xff0c;線程是否能執行取決于信號量是否允…

8.10 用redis實現緩存功能和Spring Cache

什么是緩存? 緩存(Cache), 就是數據交換的緩沖區,俗稱的緩存就是緩沖區內的數據,一般從數據庫中獲取,存儲于本地代碼。 通過Redis來緩存數據&#xff0c;減少數據庫查詢操作; 邏輯 每個分類的菜品保存一份緩存數據 數據庫菜品數據有變更時清理緩存數據 如何將商品數據緩存起…

p-級數的上界(Upper bound of p-series)

積分判別法-The Integral Test https://math.stackexchange.com/questions/2858067/upper-bound-of-p-series https://courses.lumenlearning.com/calculus2/chapter/the-p-series-and-estimating-series-value/ 兩個重要級數&#xff08;p級數和幾何級數&#xff09; ht…

WPF顯示初始界面--SplashScreen

WPF顯示初始界面–SplashScreen 前言 WPF應用程序的運行速度快&#xff0c;但并不能在瞬間啟動。當第一次啟動應用程序時&#xff0c;會有一些延遲&#xff0c;因為公共語言運行時&#xff08;CLR&#xff09;首先需要初始化.NET環境&#xff0c;然后啟動應用程序。 對于WPF中…