分析一個 .NET 寫的 某 RFID標簽系統 CPU暴漲

一:背景

1. 講故事

前段時間有位朋友說他的程序 CPU 出現了暴漲現象,由于程序是買來的,所以問題就比較棘手了,那既然找到我,就想辦法幫朋友找出來吧,分析下來,問題比較經典,有必要和大家做一下分享。

二:WinDbg 分析

1. CPU 真的爆高嗎

一直關注這個系列的朋友應該知道,用 !tp 驗證即可。

0:161>?!tp
CPU?utilization:?81%
Worker?Thread:?Total:?486?Running:?486?Idle:?0?MaxLimit:?8191?MinLimit:?24
Work?Request?in?Queue:?0
--------------------------------------
Number?of?Timers:?1
--------------------------------------
Completion?Port?Thread:Total:?6?Free:?1?MaxFree:?48?CurrentLimit:?6?MaxLimit:?1000?MinLimit:?24

果然 CPU =81% ,并且當前的 481 個工作線程全部打滿,以經驗看可能是遇到鎖什么的,不過還是先從是否觸發 GC 看起。

2. 是觸發 GC 了嗎?

要查看是否觸發 GC,可以用 !t -special 看看是否有 SuspendEE 字樣。

0:161>?!t?-special
ThreadCount:??????604
UnstartedThread:??0
BackgroundThread:?587
PendingThread:????0
DeadThread:???????11
Hosted?Runtime:???noOSID?Special?thread?type29?2e74?DbgHelper?30?1014?GC?SuspendEE?31?4a84?GC?32?4a48?GC?...52?37c0?GC?53?47a0?GC?54?4620?Finalizer?55?1aa4?ProfilingAPIAttach...

從卦中看,30號線程果然掛了 SuspendEE,并且還是一個 GC 線程,接下來切過去看看此時 GC 正在做什么?

0:161>?~~[1014]s
eax=00000000?ebx=0724fc10?ecx=00000000?edx=00000000?esi=00000000?edi=0724fc10
eip=77ddf02c?esp=0724fbd0?ebp=0724fc34?iopl=0?????????nv?up?ei?pl?nz?ac?po?nc
cs=0023??ss=002b??ds=002b??es=002b??fs=0053??gs=002b?????????????efl=00000212
ntdll!NtDelayExecution+0xc:
77ddf02c?c20800??????????ret?????8
0:030>?k#?ChildEBP?RetAddr??????
00?0724fc34?758345da?????ntdll!NtDelayExecution+0xc
01?0724fc34?738a74eb?????KERNELBASE!SleepEx+0x8a
02?0724fc78?73a0f710?????clr!EESleepEx+0x59
03?0724fc78?73a0f809?????clr!SVR::gc_heap::mark_steal+0x27c
04?0724fcd0?73a17930?????clr!SVR::gc_heap::mark_phase+0x3d0
05?0724fd0c?73a17dc9?????clr!SVR::gc_heap::gc1+0xf2
06?0724fd5c?73a174a1?????clr!SVR::gc_heap::garbage_collect+0x746
07?0724fd78?73a10d7e?????clr!SVR::gc_heap::gc_thread_function+0x14a
08?0724fd98?73a10d0f?????clr!SVR::gc_heap::gc_thread_stub+0x72
09?0724fdac?750e62c4?????clr!GCThreadStub+0x1f
0a?0724fdc0?77dd1f69?????kernel32!BaseThreadInitThunk+0x24
0b?0724fe08?77dd1f34?????ntdll!__RtlUserThreadStart+0x2f
0c?0724fe18?00000000?????ntdll!_RtlUserThreadStart+0x1b

從卦中的 gc_thread_function 函數看,這是一個阻塞版的 GC 線程,當前正處于 mark_phase 標記階段,并且還在搶其他 GC 線程的活,有點意思。。。

既然是觸發了 GC ,那就看下觸發了哪一代以及什么原因觸發的。

0:030>?x?clr!*gc_heap::settings*
73f15da8??????????clr!WKS::gc_heap::settings?=?<no?type?information>
73f13520??????????clr!SVR::gc_heap::settings?=?<no?type?information>
0:030>?dp?73f13520?
73f13520??00002df0?00000002?00000001?00000001
73f13530??00000000?00000000?00000000?00000000
73f13540??00000000?00000000?00000000?00000000
73f13550??00000000?00000000?00000005?00000001
73f13560??00000000?00000000?00000000?00000001
73f13570??00000000?0000005a?00000000?00000001
73f13580??05f71b40?86b2ee2e?00040000?00000001
73f13590??00000002?00002000?00000002?00000000

從卦中的 0000000200000005 可知,當前觸發的是 2代 GC,原因是 5,那 5 是什么意思?可以看下 clr 中的 gc_reason 即可。

enum?gc_reason
{reason_alloc_soh?=?0,reason_induced?=?1,reason_lowmemory?=?2,reason_empty?=?3,reason_alloc_loh?=?4,reason_oos_soh?=?5,reason_oos_loh?=?6,reason_induced_noforce?=?7,?//?it's?an?induced?GC?and?doesn't?have?to?be?blocking.reason_gcstress?=?8,????????//?this?turns?into?reason_induced?&?gc_mechanisms.stress_induced?=?truereason_lowmemory_blocking?=?9,reason_induced_compacting?=?10,reason_lowmemory_host?=?11,reason_pm_full_gc?=?12,?//?provisional?mode?requested?to?trigger?full?GCreason_lowmemory_host_blocking?=?13,reason_bgc_tuning_soh?=?14,reason_bgc_tuning_loh?=?15,reason_bgc_stepping?=?16,reason_max
};

也就是上面的 reason_oos_soh,表示當前的小對象堆中的段空間滿了,那是不是呢?可以用 !eeheap -gc 看下托管堆。

0:030>?!eeheap?-gc
Number?of?GC?Heaps:?24
------------------------------
Heap?0?(06d00138)
generation?0?starts?at?0xe8a380ec
generation?1?starts?at?0xe8a380e0
generation?2?starts?at?0x07311000
ephemeral?segment?allocation?context:?(0xe8a380f8,?0xe8a38104)segment?????begin??allocated??????size
07310000??07311000??0830fd5c??0xffed5c(16772444)
a86a0000??a86a1000??a969fd10??0xffed10(16772368)
e8a10000??e8a11000??e8a380f8??0x270f8(159992)
Large?object?heap?starts?at?0x1f311000segment?????begin??allocated??????size
1f310000??1f311000??1f4cafb0??0x1b9fb0(1810352)
Heap?Size:???????Size:?0x21deb14?(35515156)?bytes.
------------------------------
...
Heap?22?(06d76910)
generation?0?starts?at?0xbfd5d228
generation?1?starts?at?0xbfd5ce20
generation?2?starts?at?0x1d311000
ephemeral?segment?allocation?context:?(0xbfd5d234,?0xbfd5d240)segment?????begin??allocated??????size
1d310000??1d311000??1e30fe64??0xffee64(16772708)
bed60000??bed61000??bfd5d234??0xffc234(16761396)
Large?object?heap?starts?at?0x2a311000segment?????begin??allocated??????size
2a310000??2a311000??2a311010??0x10(16)
Heap?Size:???????Size:?0x1ffb0a8?(33534120)?bytes.
...
------------------------------
GC?Heap?Size:????Size:?0x2f6f6d18?(795831576)?bytes.

可以看到,heap 上很多都是 segment=16M ?打滿狀態,停。。。為什么 segment 只有 16M ,出現了一個重大線索。

3. 重大線索解讀

一個 Server 版的 GC,擁有高達 24 個邏輯核,居然只有 16M 的 segment,這么小的 segment,很容易被一些快進快出的大內存操作給打滿,也就更容易造成 GC 觸發,而且還是 Full GC,版本信息如下:

0:030>?!eeversion
4.7.3416.0?retail
Server?mode?with?24?gc?heaps
SOS?Version:?4.7.3416.0?retail?build

接下來到線程棧上找找有沒有快進快出的大內存操作。

4. 尋找大內存操作

既然有快進快出的操作,在 GC 觸發時肯定還會躺在 托管堆 上,我們就從這里入手。

0:030>?!dumpheap?-stat
Statistics:MT????Count????TotalSize?Class?Name
...
06cd1750???638727?????15899642??????Free
30361270???171401?????19196912?xxxx.Entities.ProductInventoryLog
30360f90???537090?????32225400?xxxx.Entities.ProductInventoryEpcDetail
30f9a148???171404?????67875600?System.Data.Entity.Core.Objects.StateManagerValue[]
3036074c???694875?????97282500?xxxx.Entities.ProductBorrow
727efd60??8419815????394836372?System.String
Total?14577631?objects
Fragmented?blocks?larger?than?0.5?MB:Addr?????Size??????Followed?by
9b0bf500????0.5MB?????????9b141878?System.Byte[]

從托管堆看,有不少的類對象,接下來抽一個 xxxx.Entities.ProductInventoryEpcDetail 看下引用,然后查根對象的 size。

0:161>?!gcroot?a8780ecc
Thread?40b8:df90d330?715d143a?System.Linq.Enumerable+<JoinIterator>d__38`4[[System.__Canon,?mscorlib],[System.__Canon,?mscorlib],[System.__Canon,?mscorlib],[System.__Canon,?mscorlib]].MoveNext()esi:?->??090eeba4?System.Linq.Enumerable+<JoinIterator>d__38`4[]...->??a8780e80?xxxx.Entities.ProductInventoryEpcDetail[]->??a8780ecc?xxxx.Entities.ProductInventoryEpcDetailFound?1?unique?roots?(run?'!GCRoot?-all'?to?see?all?roots).

其實這個引用鏈特別長,用 !objsize 090eeba4 顯示對象大小,一直都是卡住中,size 肯定不小, 接下來我們切入到 40b8 看下這個方法,可以發現一個非常復雜的 EF 寫法,又是 outer,又是 inner,又要再關聯,截圖如下:

51e95413b87b0fafb94ea2b0383906e2.png

到這里大對象操作終于找到了,我發現還有其他方法也有一些 EF 復雜操作,就不一一列舉了。

三:總結

這個 dump 給我們兩個教訓:

  1. 當 sql 很復雜時,千萬不要用 EF 去寫,這中間會產生多少個臨時對象你真的搞不清楚,你也hold不住,建議直接改成 sql,簡單粗暴。

  2. 程序盡量用 64bit 部署,否則你的 segment 會太小,太容易讓 GC 上頭了。

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

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

相關文章

linux開機引導過程總覽

簡單的說&#xff0c;系統的啟動過程如下&#xff1a; 1.開機自檢&#xff1a; 按下電源按鍵后&#xff0c;計算機硬件會主動讀取BIOS加載硬件信息并進行硬件的自我測試&#xff0c;然后系統會根據BIOS里的啟動順序讀取第一個可啟動的設備&#xff0c;從而移交系統控制權&#…

CentOS關機與重啟命令詳解

2019獨角獸企業重金招聘Python工程師標準>>> Linux centos重啟命令&#xff1a; 1、reboot  2、shutdown -r now 立刻重啟(root用戶使用)  3、shutdown -r 10 過10分鐘自動重啟(root用戶使用)  4、shutdown -r 20:35 在時間為20:35時候重啟(root用戶使用)如果…

JS正則提取字符串

河北科技師范學院歐美學院新聞標題 河南大學邁阿密學院新聞標題 首都經濟貿易大學密云分校新聞標題 北京科技大學(延慶校區)新聞標題 湖北中醫藥大學職業技術學院新聞標題 公安消防部隊高等專科學校新聞標題 從上邊的類似新聞標題中提取完整學校名稱&#xff0c;最終參考代…

【工具】PC端調試手機端 Html 頁面的工具

一、概述 有一個項目需要在手機端顯示一個 web 頁面&#xff0c;而每次把應用 launch 后&#xff0c;從手機端看比較麻煩&#xff0c;因此搜羅了幾種在 PC 端調試手機端頁面的工具。 二、工具 http://fonkie.iteye.com/blog/1846858 http://blog.csdn.net/dojotoolkit/article/…

【ArcGIS微課1000例】0031:ArcGIS中的32個拓撲規則(圖文詳解)

在地理數據庫中,拓撲是定義點要素、線要素以及面要素共享重疊幾何的方式的排列布置。例如,街道中心線與人口普查區塊共享公共幾何,相鄰的土壤面共享公共邊界。學習拓撲就必須掌握ArcGIS中常見的拓撲規則。 文章目錄 一、面的拓撲規則(10種)二、點的拓撲規則(6種)三、線的…

Blazor University (38)JavaScript 互操作 —— 從 .NET 調用 JavaScript

原文鏈接&#xff1a;https://blazor-university.com/javascript-interop/calling-javascript-from-dotnet/從 .NET 調用 JavaScriptJavaScript 應添加到服務器端 Blazor 應用程序的 /Pages/_Host.cshtml 或 Web Assembly Blazor 應用程序的 wwwroot/index.html 中。然后可以通…

十大排序總結(js實現、穩定性、內外部排序區別、時間空間復雜度、冒泡、快速、直接選擇、堆、直接插入、希爾、桶、基數、歸并、計數排序)

目錄 排序相關概念 穩定性 內部排序 外部排序 十種排序算法特點總結 交換排序 冒泡排序&#xff08;數組sort方法的原理&#xff09; 圖解 js實現 特點 快速排序 圖解 js實現 特點 選擇排序 直接選擇排序 圖解 js實現 特點 堆排序 大&#xff08;小&#xff0…

三維重建技術概述

基于視覺的三維重建&#xff0c;指的是通過攝像機獲取場景物體的數據圖像&#xff0c;并對此圖像進行分析處理&#xff0c;再結合計算機視覺知識推導出現實環境中物體的三維信息。 1. 相關概念 &#xff08;1&#xff09;彩色圖像與深度圖像 彩色圖像也叫作RGB圖像&#xff0c;…

【ArcGIS微課1000例】0032:ArcGIS中河流(曲線)、湖泊(水體色)圖例制作案例教程

河流作為線要素,在符號化的過程中使用的大多都是直線符號,但是為了能夠在出圖的使用表現形象的河流對象,就有了使用曲線表示河流圖例的需求,湖泊亦是如此。本文講解在ArcGIS中制作標準的河流和湖泊圖例的完整教程。 文章目錄 一、案例效果二、圖例制作三、圖例修改一、案例…

從shiro源碼角度學習工廠方法設計模式

緒論 shiro是一個簡單易用&#xff0c;功能強大的Java安全框架&#xff0c;學習其源碼設計思想對我們的編碼水平的提高大有裨益。現在&#xff0c;就從源碼角度帶大家學習一下shiro里面的工廠方法模式。 這里的前提是讀者有過使用shiro的基礎&#xff0c;沒有也行&#xff0c;關…

淺談微信小程序對于房地產行業的影響

前幾日&#xff0c;我們曾經整理過一篇文章是關于微信小程序對于在線旅游業的影響的一些反思&#xff08;淺談微信小程序對OTA在線旅游市場的影響&#xff09;&#xff0c;近日由于生活工作的需要走訪了一些房地產的住宅商品房&#xff0c;突然想到微信小程序對于房地產行業會有…

新型基礎測繪與實景三維中國建設技術文件【1】名詞解釋

文章目錄一、新型基礎測繪 new fundamental surveying and mapping**二、實景三維 3D real scene**三、時空大數據平臺 spatio-temporal big data platform**四、地理實體 geo-entity**五、基礎地理實體 fundamental geo-entity**六、組合地理實體數據 combined geo-entity dat…

Android.bp 和 Android.mk 的對應關系

參考 Soong 構建系統 Android.mk 轉為 Android.bp 沒有分支、循環等流程控制的簡單的 Android.mk &#xff0c;可以通過 androidmk 命令轉化為 Android.bp source 、lunch 之后執行即可。 androidmk Android.mk > Android.bp對應關系 Android 13 &#xff0c;build/soon…

深入理解javascript原型和閉包

原文鏈接http://www.cnblogs.com/wangfupeng1988/p/3977924.html 對象是屬性的集合。 function show(x) {console.log(typeof(x)); // undefinedconsole.log(typeof(10)); // numberconsole.log(typeof(abc)); // stringconsole.log(typeof(true)); // booleanconsole.lo…

薪資高壓線

閱讀本文大概需要5分鐘。最近一名讀者咨詢一個問題&#xff1a;洋哥&#xff0c;最近公司有一名同事因為打探其他人薪資被開除了&#xff0c;為啥我們公司要把薪資設置為高壓線。這是個好問題&#xff0c;解答完他的疑惑后想起了一年多前寫過一篇&#xff0c;彼時讀者還比較少&…

達摩院年終預測出爐:2022 十大科技趨勢,AI for Science 高居榜首

作為“一所探索科技未知的研究院”&#xff0c;阿里巴巴達摩院成立至今已經四年了。 這四年來&#xff0c;達摩院秉持著“探索科技位置&#xff0c;以人類愿景為驅動力&#xff0c;開展基礎科學和顛覆式技術創新研究”的原則與使命&#xff0c;在基礎科研和硬科技發展上“遍地生…

chrome調試工具高級不完整使用指南(基礎篇)

一、前言 本文記錄的是作者在工作上面對chrome的一些使用和情況的分析分享&#xff0c;內容僅代表個人的觀點。轉發請注明出處(http://www.cnblogs.com/st-leslie/),謝謝合作 二、瀏覽器模塊介紹 由于chrome瀏覽器一直在不斷的進行更新迭代&#xff0c;會不斷的新增功能&#x…

新型基礎測繪與實景三維中國建設技術文件【2】基礎地理實體分類、粒度及精度基本要求

《新型基礎測繪體系建設試點技術大綱》指出&#xff0c;新型基礎測繪將以“基礎地理實體”為核心的成果模式創新為切入點&#xff0c;帶動技術體系、生產組織體系和政策標準體系的全面創新&#xff0c;從而實現基礎測繪高質量發展。 基礎地理實體作為新型基礎測繪產品體系的核心…

構建和實現單點登錄解決方案(轉載于IBMdeveloperWorks)

將一個開放源碼的基于 Java 的身份驗證組件集成進 Web 門戶中 在現有的應用程序中實現單點登錄解決方案&#xff08;single sign-on&#xff0c;SSO&#xff0c;即登錄一次&#xff0c;就可以向所有網絡資源驗證用戶的身份&#xff09;是非常困難的&#xff0c;但是在構建復雜的…

分享一個基于Abp 和Yarp 開發的API網關項目

這個項目起源于去年公司相要嘗試用微服務構建項目,在網關的技術選型中,我們原本確認了ApiSix 網關,如果需要寫網關插件需要基于Lua腳本去寫,我和另外一個同事當時基于這個寫了一個簡單的插件,但是開發測試以及發布都很麻煩,而且使用Lua腳本作為插件的開發語言本身也不是我們強項…