記一次 .NET 差旅管理后臺 CPU 爆高分析

一:背景

1. 講故事

前段時間有位朋友在微信上找到我,說他的 web 系統 cpu 運行一段時候后就爆高了,讓我幫忙看一下是怎么回事,那就看吧,聲明一下,我看 dump 是免費的,主要是錘煉自己技術,沒有某軟工程師高額的技術分析費。😅😅😅

閑話不多說,我們上 windbg 說話。

二:WinDbg 分析

1. CPU 真的爆高嗎

是否真的爆高,我們得自己先驗證下,使用 !tp 命令看一下即可。

0:065>?!tp
CPU?utilization:?81%
Worker?Thread:?Total:?32?Running:?7?Idle:?25?MaxLimit:?8191?MinLimit:?32
Work?Request?in?Queue:?1AsyncTimerCallbackCompletion?TimerInfo@018eedc8
--------------------------------------
Number?of?Timers:?1
--------------------------------------
Completion?Port?Thread:Total:?4?Free:?4?MaxFree:?64?CurrentLimit:?4?MaxLimit:?1000?MinLimit:?32

從卦象看,確實存在 CPU 爆高的情況,根據過往經驗,托管程序爆高大多是因為GC觸發所致,但觸發 GC 的原因千奇百怪,畢竟在 clr 層面 GC 觸發的原因高達 14 種,代碼如下:

static?const?char*?const?str_gc_reasons[]?=
{"alloc_soh","induced","lowmem","empty","alloc_loh","oos_soh","oos_loh","induced_noforce","gcstress","induced_lowmem","induced_compacting","lowmemory_host","pm_full_gc","lowmemory_host_blocking"
};

2. 真的是 GC 觸發嗎

驗證當前程序是否為 GC 觸發,方式有很多,可以用 !t 或者 !t -special,但這兩種方式不是特別準,最準的就是根據GC模式直接到 CLR 里去搜全局變量 clr!SVR::gc_heap::gc_started 的值就可以了,參考如下:

0:038>?dp?clr!SVR::gc_heap::gc_started?L1
712d3190??00000001

可以看到,此時的 gc_started=1,說明 GC 是觸發狀態,接下來可以從所有的線程棧中搜 garbage_collect 或者 gc1 什么的關鍵詞即可。

0:038>?k#?ChildEBP?RetAddr??????
00?0318f934?70de8248?????clr!SVR::gc_heap::relocate_survivor_helper+0x1ea
01?0318f944?70de83df?????clr!SVR::gc_heap::relocate_survivors_in_plug+0x24
02?0318f970?70de84ac?????clr!SVR::gc_heap::relocate_survivors_in_brick+0x70
03?0318f9a8?70de830b?????clr!SVR::gc_heap::relocate_survivors+0xe4
04?0318fa00?70de218a?????clr!SVR::gc_heap::relocate_phase+0xb9
05?0318fbb4?70de18bf?????clr!SVR::gc_heap::plan_phase+0x136e
06?0318fbec?70de1d49?????clr!SVR::gc_heap::gc1+0x101
07?0318fc3c?70de1421?????clr!SVR::gc_heap::garbage_collect+0x746
08?0318fc58?70ddacde?????clr!SVR::gc_heap::gc_thread_function+0x14a
09?0318fc6c?70ddac6f?????clr!SVR::gc_heap::gc_thread_stub+0x72
0a?0318fc80?770a6a14?????clr!GCThreadStub+0x1f
0b?0318fc94?77e4a9ef?????kernel32!BaseThreadInitThunk+0x24
0c?0318fcdc?77e4a9ba?????ntdll!__RtlUserThreadStart+0x2f
0d?0318fcec?00000000?????ntdll!_RtlUserThreadStart+0x1b

從卦象看,gc_thread_stub 表示當前是一個 GC 線程,它正在處于 relocate_phase 階段,這表明當前是一個 壓縮回收,GC回收流程圖可以看下官方文檔。

GarbageCollectGeneration(){SuspendEE();garbage_collect();RestartEE();}garbage_collect(){generation_to_condemn();gc1();}gc1(){mark_phase();plan_phase();}plan_phase(){//?actual?plan?phase?work?to?decide?to?//?compact?or?notif?(compact){relocate_phase();compact_phase();}elsemake_free_lists();}

在這個階段,托管堆也會是損壞狀態,你可以用 ?!dumpheap -stat 驗證下。

0:038>?!dumpheap?-stat
The?garbage?collector?data?structures?are?not?in?a?valid?state?for?traversal.
It?is?either?in?the?"plan?phase,"?where?objects?are?being?moved?around,?or
we?are?at?the?initialization?or?shutdown?of?the?gc?heap.?Commands?related?to?
displaying,?finding?or?traversing?objects?as?well?as?gc?heap?segments?may?not?
work?properly.?!dumpheap?and?!verifyheap?may?incorrectly?complain?of?heap?
consistency?errors.
Object?<exec?cmd="!ListNearObj?/d?03301000">03301000</exec>?has?an?invalid?method?table.

3. 為什么會出現壓縮回收

一般來說,GC 分清除和壓縮回收,后者屬于一種重量級操作,很傷GC,在臨時段上還稍微好一些,接下來我們看下當前 GC 是在回收哪一代?可以到 CLR 里面去查一下判決代字段。clr!WKS::GCHeap::GcCondemnedGeneration

0:038>?dp?clr!SVR::GCHeap::GcCondemnedGeneration?L1
712d79d8??00000002

糟了,結果是個 2,這個 2 表示 fullGC, 也就是全量回收,大多對應著 gc_reason=lowmem 的情況,也就是內存不足。

4. 真的內存不足嗎

要想找到答案,我們用 !address -summary 看下當前的虛擬內存情況。

0:038>?!address?-summary---?Usage?Summary?----------------?RgnCount?-----------?Total?Size?--------?%ofBusy?%ofTotal
<unknown>??????????????????????????????1835??????????dce6e000?(???3.452?GB)??91.56%???86.29%
Image???????????????????????????????????842???????????f436000?(?244.211?MB)???6.33%????5.96%
Free????????????????????????????????????312???????????eba5000?(?235.645?MB)????????????5.75%
Stack???????????????????????????????????451???????????2d80000?(??45.500?MB)???1.18%????1.11%
Heap?????????????????????????????????????72???????????2342000?(??35.258?MB)???0.91%????0.86%
TEB?????????????????????????????????????150?????????????96000?(?600.000?kB)???0.02%????0.01%
Other?????????????????????????????????????7?????????????4e000?(?312.000?kB)???0.01%????0.01%
PEB???????????????????????????????????????1??????????????1000?(???4.000?kB)???0.00%????0.00%---?Type?Summary?(for?busy)?------?RgnCount?-----------?Total?Size?--------?%ofBusy?%ofTotal
MEM_PRIVATE????????????????????????????2051??????????dd635000?(???3.459?GB)??91.76%???86.48%
MEM_IMAGE??????????????????????????????1267??????????11ad1000?(?282.816?MB)???7.33%????6.90%
MEM_MAPPED???????????????????????????????40???????????2345000?(??35.270?MB)???0.91%????0.86%---?State?Summary?----------------?RgnCount?-----------?Total?Size?--------?%ofBusy?%ofTotal
MEM_COMMIT?????????????????????????????2604??????????cbe7d000?(???3.186?GB)??84.51%???79.65%
MEM_RESERVE?????????????????????????????754??????????255ce000?(?597.805?MB)??15.49%???14.60%
MEM_FREE????????????????????????????????312???????????eba5000?(?235.645?MB)????????????5.75%---?Largest?Region?by?Usage?-----------?Base?Address?--------?Region?Size?----------
<unknown>????????????????????????????????????3300000??????????20087000?(?512.527?MB)
Image???????????????????????????????????????6f819000????????????f5f000?(??15.371?MB)
Free????????????????????????????????????????fea50000???????????1590000?(??21.562?MB)
Stack????????????????????????????????????????3110000?????????????7a000?(?488.000?kB)
Heap????????????????????????????????????????3bc80000????????????621000?(???6.129?MB)
TEB?????????????????????????????????????????fe6e5000??????????????1000?(???4.000?kB)
Other???????????????????????????????????????fea10000?????????????33000?(?204.000?kB)
PEB?????????????????????????????????????????fea49000??????????????1000?(???4.000?kB)

從卦象看,當前的 MEM_COMMIT=3.186G, 最大的Free塊 Free=15.371MB,再根據之前展示的內存地址,我們發現這個程序是 32bit ,跑了 64bit 機器上,這種情況下程序最多可占用 4G 內存空間,雖然 MEM_RESERVE= 597.805 MB, 但這種 RESERVE 是零散的,本質上來說此時的程序處于虛擬地址緊張,由于 虛擬地址 緊張,導致 GC 在不斷的做 全量內存 回收。

三:總結

根據上面的分析, GC 觸發的原因主要還是 32bit 程序的 4G 內存限制所致, 導致 GC 在不停的做全量回收,這種場景真的讓 GC 很尷尬,優先解決辦法就是將程序改成 64bit,后面再看看如何優化程序內存,畢竟現在托管堆處于損壞狀態,也不好分析啦。

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

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

相關文章

C語言試題124之給一個不多于 5 位的正整數,要求:一、求它是幾位數,二、逆序打印出各位數字

C語言試題124之給一個不多于 5 位的正整數,要求:一、求它是幾位數,二、逆序打印出各位數字 47/100 發布文章 u011068702 未選擇任何文件 new ?作者簡介:大家好我是碼莎拉蒂,CSDN博客專家?????? ??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模…

C#數組原來這么簡單,你學廢了嗎?

文章目錄 5.1 數組的概念5.2 數組聲明與初始化5.3 數組的基本操作與排序5.4 多維數組小結5.1 數組的概念 1.數組與數組元素 數組是相同類型的對象的集合。 一個數組可以含有若干個下標變量(或稱數組元素),下標也叫索引(Index),用來指出某個數組元素在數組中的位置。 數組…

數據基本類型以及相關舉例

數據基本類型&#xff1a; 整型&#xff1a;字節型byte 短整型short 整型int 浮點類型&#xff1a;長整形long 浮點型 fioat 雙精度性double 字符型&#xff1a;char 布爾型&#xff1a;boolean引用類型&#xff08; reference&#xff09;&#xff1a;類class 接口inte…

android--Activity有返回值的跳轉

AndroidManifest.xml <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"package"com.hanqi.test4"><applicationandroid:allowBackup"true"and…

[轉]ES6、ES7、ES8、ES9、ES10新特性一覽 (個人整理,學習筆記)

目錄 1.ES6新特性&#xff08;2015&#xff09; 1.1模塊化(Module) 1.1.1導出(export) 1.1.2導入(import) 1.2箭頭&#xff08;Arrow&#xff09;函數 1.2.1箭頭函數的結構 1.3默認參數 1.4模板字符串 1.5.結構賦值 1.5.1數組的結構賦值 1.5.2對象的結構賦值 1.6延…

使用ML.NET+ONNX預訓練模型整活B站經典《華強買瓜》

前言最近在看微軟開源的機器學習框架ML.NET使用別人的預訓練模型(開放神經網絡交換格式.onnx)來識別圖像&#xff0c;然后逛github發現一個好玩的repo。決定整活一期博客。首先還是稍微科普一下機器學習相關的知識&#xff0c;這一塊.NET雖然很早就開源了ML.NET框架&#xff0c…

C語言試題125之一個 5 位數,判斷它是不是回文數。即 12321 是回文數,個位與萬位相同,十位與千位相同

?作者簡介:大家好我是碼莎拉蒂,CSDN博客專家?????? ??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 1、題目 題目:一個 5 位數,判斷它是不是回文數。即 12321 是回文數,個位與萬位相同,十位與千位相…

不會C# Winform用戶界面設計?是因為沒有掌握這些控件(建議收藏)

文章目錄 6.1 常用控件6.1.1 單選按鈕(RadioButton)6.1.2 復選框(CheckBox)6.1.3 框架1. 面板控件Panel2. 分組框GroupBox3. TabControl控件6.1.4 應用實例6. 2 列表框和組合框6.2.1 列表框(ListBox)6.2.2 組合框(ComboBox )6.2.3 應用實例6.3 用戶交互界面6.3.1 滾動條和進度條…

痞子衡嵌入式:ARM Cortex-M內核那些事(2)- 第一款微控制器

大家好&#xff0c;我是痞子衡&#xff0c;是正經搞技術的痞子。今天痞子衡給大家介紹的是第一款Cortex-M微控制器。 1.天生榮耀&#xff1a;ARM Cortex-M處理器由來 ARM公司自2004年推出ARMv7內核架構時&#xff0c;摒棄了以往"ARM數字"這種處理器命名方法&#xff…

SQL Server在更改計算機名后的設置

把原來的賬號刪除 再添加現有的賬號 添加權限 搞定了上面的賬號配置&#xff0c;接下來就是設置服務器名稱 參考&#xff1a;http://www.cnblogs.com/EasonJim/p/6114249.html 后話&#xff1a;當初為了設置這個問題&#xff0c;選擇了重裝SQL Server&#xff0c;但是也是無用的…

Jupyter Notebook 入門指南

簡介 Jupyter Notebook&#xff08;此前被稱為 IPython notebook&#xff09;是一個交互式筆記本&#xff0c;支持運行 40 多種編程語言。 Jupyter Notebook 的本質是一個 Web 應用程序&#xff0c;便于創建和共享文學化程序文檔&#xff0c;支持實時代碼&#xff0c;數學方程…

C語言試題127之 100 之內的素數

?作者簡介:大家好我是碼莎拉蒂,CSDN博客專家?????? ??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 1、題目 題目:求 100 之內的素數 2 、溫馨提示 想獲取更多C語言題目請猛搓這里==========》200個C語…

學弟學妹們,C#為啥學不好?是因為你沒真正理解面向對象的思想!

文章目錄 7.1面向對象的基本概念7.1.1 什么是面向對象編程7.1.2 面向對象編程的特點7.2 類7.2.1 類的概念7.2.2 類的聲明7.2.3 類的成員7.2.4 類成員訪問修飾符7.3 對象7.4 構造函數和析構函數7.4.1 構造函數7.4.2 析構函數7.5 方法7.5.1 方法的聲明7.5.2 方法的參數7.5.3 靜態…

MongoDB中的分組

一.MongoDB中的Count函數、Distinct函數以及分組 準備工作&#xff0c;插入一個班級的文檔 > for(var i0;i<10;i){ ... db.Classes.insert({ClassName:"Class"i,_id:i}); ... } WriteResult({ "nInserted" : 1 }) > db.Classes.find() { "_i…

在 .NET 6 項目中使用 Startup.cs

對于 .NET 6 項目&#xff0c;現在已經找不到 Startup.cs 文件。默認情況下&#xff0c;此文件已經被刪除&#xff0c;并且 Program.cs 是配置依賴注入服務和 Middleware 的新位置。但是&#xff0c;有些人可能更喜歡使用 Startup.cs , 并且我也是&#xff0c;可能已經習慣了&a…

編寫iptables腳本實現IP地址、端口過濾

實驗案例&#xff1a;公司使用一臺運行RHEL5系統的服務器作為網關&#xff0c;分別連接三個網絡&#xff0c;其中LAN1為普通員工電腦所在的局域網&#xff0c;LAN2為DNS緩存服務器所在的局域網。eth0通過10M光纖接入Internet。為了有效的管理網絡環境及增強內部網絡的安全性&am…

讓VS Code 支持 Jupyter Notebook

一、Jupyter Notebook Jupyter Notebook是基于網頁的用于交互計算的應用程序。其可被應用于全過程計算&#xff1a;開發、文檔編寫、運行代碼和展示結果。——Jupyter Notebook官方介紹。 Jupyter Notebook是以網頁的形式打開&#xff0c;可以在網頁頁面中直接編寫代碼和運行代…

C語言試題128之對 10 個數進行排序

?作者簡介:大家好我是碼莎拉蒂,CSDN博客專家?????? ??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 1、題目 題目:對 10 個數進行排序 分析:可以利用選擇法,即從后 9 個比較過程中,選擇一個最小的與…

JavaScript設計模式

JavaScript的設計模式&#xff1a; 1、單例模式 單例模式&#xff08;Singleton&#xff09;&#xff0c;整個運行期間只會被初始化一次。該模式簡單易懂&#xff0c;運用也很廣泛。可以用它來聚合公共的方法&#xff0c;形成一個工具類&#xff0c;對外提供api。 var single …

Windows 11 23H2 25145 推送!全新隱私設置和 OneDrive 體驗

面向 Dev 頻道的 Windows 預覽體驗成員&#xff0c;微軟現已推送 Windows 11 預覽版 Build 25145。主要變化1.微軟宣布為 Windows 11 設置引入全新 OneDrive 體驗&#xff0c;您可以在設置中查看 OneDrive 云存儲服務的訂閱詳情&#xff0c;包括付費方式、容量大小和定期付費等…