記一次 .NET 某新能源系統 線程瘋漲 分析

一:背景

1. 講故事

前段時間收到一個朋友的求助,說他的程序線程數瘋漲,尋求如何解決。

09b7e4b1cd48274b8444afe85e520bef.png

等我分析完之后,我覺得這個問題很有代表性,所以拿出來和大家分享下,還是上老工具 WinDbg。

二:WinDbg 分析

1. 線程真的在瘋漲嗎

要想查線程有沒有瘋漲,可以用 !t 命令看一下。

0:000:x86>?!t
ThreadCount:??????382
UnstartedThread:??1
BackgroundThread:?376
PendingThread:????0
DeadThread:???????2
Hosted?Runtime:???noLock??ID?OSID?ThreadOBJ????State?GC?Mode?????GC?Alloc?Context??Domain???Count?Apt?Exception0????1??59c?00e52fb0?????26020?Preemptive??12D67610:00000000?00e4b408?0?????STA?2????2?2b30?00e61aa0?????2b220?Preemptive??00000000:00000000?00e4b408?0?????MTA?(Finalizer)?3????3?18cc?00ea72b8???202b220?Preemptive??00000000:00000000?00e4b408?0?????MTA?5????4?1f18?00f02998???1020220?Preemptive??00000000:00000000?00e4b408?0?????Ukn?(Threadpool?Worker)?
XXXX????6????0?00f056f8?????39820?Preemptive??00000000:00000000?00e4b408?0?????MTA?6????7?2154?09052448???202b020?Preemptive??12E353E0:00000000?00e4b408?0?????MTA?...377??373?2ee8?21a90958???1029220?Preemptive??12D1FCCC:00000000?00e4b408?0?????MTA?(Threadpool?Worker)?378??374?227c?21b1d510???1029220?Preemptive??12DCBFC8:00000000?00e4b408?0?????MTA?(Threadpool?Worker)?379??375??7e8?21b1baa8???1029220?Preemptive??12D39ADC:00000000?00e4b408?0?????MTA?(Threadpool?Worker)?380??376?1d1c?21a8fec8???1029220?Preemptive??12D11F40:00000000?00e4b408?0?????MTA?(Threadpool?Worker)?381??366?19ec?215c1bd0???1029220?Preemptive??12DB42D8:00000000?00e4b408?0?????MTA?(Threadpool?Worker)?382??377?1dc8?21b1bff0???1029220?Preemptive??12C71F9C:00000000?00e4b408?0?????MTA?(Threadpool?Worker)?383??378??f94?215bc750???1029220?Preemptive??12E10568:00000000?00e4b408?0?????MTA?(Threadpool?Worker)?384??379?17d4?21ac5580???1029220?Preemptive??12D8EE98:00000000?00e4b408?0?????MTA?(Threadpool?Worker)?385??381?2c1c?21b1b018???1029220?Preemptive??12D0DD00:00000000?00e4b408?0?????MTA?(Threadpool?Worker)?386??380?309c?21b1da58???1029220?Preemptive??12E25028:00000000?00e4b408?0?????MTA?(Threadpool?Worker)?387??382?3048?21ac6aa0???1029220?Preemptive??12DFA918:00000000?00e4b408?0?????MTA?(Threadpool?Worker)

從卦中看,主線程是一個 STA,說明是一個窗體程序,一個窗體能做到 387 個線程,也是挺牛的,同時也能觀察到大多都是 ThreadPool Worker ,也就是線程池工作線程。

2. 這些線程都在干嘛

這里有一個小技巧,那就是線程號越大,往往都是最新創建的,往往從這里面就能套出來一些有用的東西,言外之意就扒一扒 380 ~ 387 這些線程的調用棧。

0:387:x86>?~387s
ntdll_77380000!NtWaitForSingleObject+0xc:
773f29dc?c20c00??????????ret?????0Ch
0:387:x86>?k
CvRegToMachine(x86)?conversion?failure?for?0x14f
X86MachineInfo::SetVal:?unknown?register?0?requested#?ChildEBP?RetAddr??????
00?31fef104?755a1539?????ntdll_77380000!NtWaitForSingleObject+0xc
01?31fef104?74b3ee3b?????KERNELBASE!WaitForSingleObjectEx+0x99
02?31fef168?74b3efed?????clr!CLRSemaphore::Wait+0xbe
03?31fef19c?74b3eee2?????clr!ThreadpoolMgr::UnfairSemaphore::Wait+0x13a
04?31fef204?74a54c27?????clr!ThreadpoolMgr::WorkerThreadStart+0x328
05?31feff24?7649fa29?????clr!Thread::intermediateThreadProc+0x58
06?31feff34?773e7a7e?????kernel32!BaseThreadInitThunk+0x19
07?31feff90?773e7a4e?????ntdll_77380000!__RtlUserThreadStart+0x2f
0:387:x86>?~386s
ntdll_77380000!NtWaitForSingleObject+0xc:
773f29dc?c20c00??????????ret?????0Ch
0:386:x86>?k
CvRegToMachine(x86)?conversion?failure?for?0x14f
X86MachineInfo::SetVal:?unknown?register?0?requested#?ChildEBP?RetAddr??????
00?31d6ede4?755a1539?????ntdll_77380000!NtWaitForSingleObject+0xc
01?31d6ede4?74b3ee3b?????KERNELBASE!WaitForSingleObjectEx+0x99
02?31d6ee48?74b3efed?????clr!CLRSemaphore::Wait+0xbe
03?31d6ee7c?74b3eee2?????clr!ThreadpoolMgr::UnfairSemaphore::Wait+0x13a
04?31d6eee4?74a54c27?????clr!ThreadpoolMgr::WorkerThreadStart+0x328
05?31d6fb84?7649fa29?????clr!Thread::intermediateThreadProc+0x58
06?31d6fb94?773e7a7e?????kernel32!BaseThreadInitThunk+0x19
07?31d6fbf0?773e7a4e?????ntdll_77380000!__RtlUserThreadStart+0x2f
0:386:x86>?~385s
ntdll_77380000!NtWaitForSingleObject+0xc:
773f29dc?c20c00??????????ret?????0Ch
0:385:x86>?k
CvRegToMachine(x86)?conversion?failure?for?0x14f
X86MachineInfo::SetVal:?unknown?register?0?requested#?ChildEBP?RetAddr??????
00?31eaee64?755a1539?????ntdll_77380000!NtWaitForSingleObject+0xc
01?31eaee64?74b3ee3b?????KERNELBASE!WaitForSingleObjectEx+0x99
02?31eaeec8?74b3efed?????clr!CLRSemaphore::Wait+0xbe
03?31eaeefc?74b3eee2?????clr!ThreadpoolMgr::UnfairSemaphore::Wait+0x13a
04?31eaef64?74a54c27?????clr!ThreadpoolMgr::WorkerThreadStart+0x328
05?31eafb7c?7649fa29?????clr!Thread::intermediateThreadProc+0x58
06?31eafb8c?773e7a7e?????kernel32!BaseThreadInitThunk+0x19
07?31eafbe8?773e7a4e?????ntdll_77380000!__RtlUserThreadStart+0x2f

從線程棧上看,這些線程都在 UnfairSemaphore 處等待,這是一個正常現象,因為這些線程都是通過 UnfairSemaphore 鎖來喚醒,不過奇怪的是,這些線程為什么產生,又為什么不被消亡?

根據經驗預測:肯定有代碼在不斷的調度 線程池 線程,然后又做了一個短命的操作,導致線程池線程不斷新增,又得不到線程可以被消亡的閾值。

3. 程序真的在頻繁調度線程嗎

既然猜測是程序在頻繁的調用線程池線程,能做的只能是觀察此時 dump 中的所有線程的線程棧,看能不能挖到點有價值的東西,可以使用 ~*e !clrstack 命令。

c436f056f0cfba665580eb63a4a2ba28.png

經過仔細觀察這近400個線程棧,發現有 37 處都是 System.Threading.Thread.Sleep(Int32), 而且大多都是 HslCommunication.Core.Net.NetworkBase.ThreadPoolCheckTimeOut(System.Object) 函數,能清楚的看到是由線程池發起的,接下來就是用 ILSpy 反編譯下這個函數看下到底是怎么回事。

protected?void?ThreadPoolCheckTimeOut(object?obj){HslTimeOut?hslTimeOut;if?((hslTimeOut?=?obj?as?HslTimeOut)?==?null){return;}while?(!hslTimeOut.IsSuccessful){Thread.Sleep(100);if?((DateTime.Now?-?hslTimeOut.StartTime).TotalMilliseconds?>?(double)hslTimeOut.DelayTime){if?(!hslTimeOut.IsSuccessful){LogNet?.WriteWarn(ToString(),?"Wait?Time?Out?:?"?+?hslTimeOut.DelayTime);hslTimeOut.Operator?.Invoke();hslTimeOut.WorkSocket?.Close();}break;}}}

接下來通過 ILSpy 查看這個方法的引用,發現有很多處,抽幾個如下:

protected?OperateResult<TNetMessage>?ReceiveMessage<TNetMessage>(Socket?socket,?int?timeOut,?TNetMessage?netMsg)?where?TNetMessage?:?INetMessage{...if?(timeOut?>?0){ThreadPool.QueueUserWorkItem(ThreadPoolCheckTimeOut,?hslTimeOut);}...}protected?OperateResult<Socket>?CreateSocketAndConnect(IPEndPoint?endPoint,?int?timeOut){...ThreadPool.QueueUserWorkItem(ThreadPoolCheckTimeOut,?hslTimeOut);...}protected?void?CreateSocketAndConnect(IPEndPoint?endPoint,?int?timeOut,?Action<OperateResult<Socket>>?connectCallback){...ThreadPool.QueueUserWorkItem(ThreadPoolCheckTimeOut,?hslTimeOut);...}

從上面代碼看,確實存在一些商榷的地方,很多的 socket 操作都用線程池來處理 ThreadPoolCheckTimeOut() 函數,而在這個函數內當 hslTimeOut.IsSuccessful =false 的時候,在 if ((DateTime.Now - hslTimeOut.StartTime).TotalMilliseconds > (double)hslTimeOut.DelayTime) 不滿足的時間區間內會一直 sleep,這就導致當 socket 請求量上去后,導致很多線程處于 sleep 狀態, 線程池又不得不生成更多的線程來處理 ThreadPoolCheckTimeOut() 邏輯。

到這里終于就找到了符合 線程池線程 瘋漲的底層邏輯,接下來看看 HslCommunication.dll 為何物,去找一下它的類庫聲明。

[assembly:?CompilationRelaxations(8)]
[assembly:?RuntimeCompatibility(WrapNonExceptionThrows?=?true)]
[assembly:?Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly:?AssemblyTitle("HslCommunication")]
[assembly:?AssemblyDescription("一個框架庫,包含完善的網絡通信及日志組件")]
[assembly:?AssemblyConfiguration("")]
[assembly:?AssemblyCompany("")]
[assembly:?AssemblyProduct("HslCommunication")]
[assembly:?AssemblyCopyright("Copyright???By?Richard.Hu?2018")]
[assembly:?AssemblyTrademark("")]
[assembly:?ComVisible(false)]
[assembly:?Guid("d3710b78-1b32-4d53-9604-0451a795a2f5")]
[assembly:?AssemblyFileVersion("5.3.2.0")]
[assembly:?AssemblyVersion("5.3.2.0")]

可以看到,這是一個商業組件。

80683a61901fab15d395e5be5ff6cf30.png

三:總結

由于定位到疑似是 HslCommunication 組件的問題,看了下還是 商業版 , 這就尷尬了,建議的解決辦法如下:

1) 短期:

ThreadPool.SetMaxThreads 限定線程上限。

2) 長期:

找作者看看有沒有最新版,或者到 https://github.com/dathlin/HslCommunication 上提一個 issue,讓別人系統性解決一下。

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

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

相關文章

【原創】請避免GO語言中的攜程空跑(CPU突然激增)

其實GO語言從1.6版本開始非常不錯了&#xff0c;GC性能優化非常到位&#xff0c;并且各種并行設計比從新實現一套C版本的確是方便不少。 語言包也很多&#xff0c;庫也相對穩定&#xff0c;完全可以適用于生產環境。 本文主要是給剛剛入門新手注意一個攜程空跑的問題&#xff0…

在Linux上啟動oracle 11g OEM

[rootfmw ~]# su - oracle[oraclefmw ~]$ emctl start dbconsole轉載于:https://blog.51cto.com/weichanglong/1762783

[轉]ES7、ES8、ES9、ES10新特性大盤點

ES7、ES8、ES9、ES10新特性大盤點 本文轉自&#xff1a;https://mp.weixin.qq.com/s/8bov6788ivV0sHzmwrn5lw 以下文章來源于前端工匠 &#xff0c;作者浪里行舟君 前端工匠 我是浪里行舟&#xff0c;Github博客4000star作者&#xff0c;致力于打造一系列能夠幫助初中級工程師…

熱榜!!!數據結構與算法:C語言版---數組與稀疏矩陣---強勢來襲!

數組是各種計算機語言中經常使用到的重要數據結構&#xff0c;一般的說&#xff1a;在內存中申請一片連續地址的存儲空間、存儲這些數、就稱為數組。 在C語言中&#xff0c;申請連續的存儲空間是很容易的事情&#xff0c;但難在多維數組的組織、以及數組數據的壓縮上&#xff…

C語言試題167之字符串加密和解密算法

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:在本實例…

第一聲問候

前一篇《Emacs 是一臺計算機》理解了 Emacs 身為計算機的本質之后&#xff0c;在 Emacs 里編程就順理成章了。不過&#xff0c;在此之前&#xff0c;還需要略微介紹一下 Emacs 最基本的操作。 系統的不一致&#xff0c;令人有點煩躁 現在&#xff0c;也可以坦然地說&#xff0c…

破解支付寶AR紅包

支付寶新出的AR紅包沒多久&#xff0c;就有人破解了&#xff0c;大致原理是將上面的像素條遮擋下面的黑條&#xff0c;基本上得到模糊的圖就可以掃到紅包。不過現在大多是ps解決&#xff0c;那得有多麻煩啊&#xff0c;所以我用java寫了一個&#xff0c;效果還不錯。 先截屏&am…

在 Windows 上搭建配置 Jenkins 然后編譯打包 VS 項目

在 Windows 上搭建配置 Jenkins 然后編譯打包 VS 項目獨立觀察員 2022 年 7 月 6 日一、安裝1、下載并安裝 JRE &#xff08;Java 運行環境&#xff09;。2、下載 Windows 版本的 Jenkins 安裝包并安裝。3、安裝 Visual Studio&#xff0c;以供編譯項目使用。4、安裝 Advanced …

【ArcGIS微課1000例】0007:基于數字高程模型DEM生成剖面線、剖面圖

文章目錄 效果預覽數據分析工具介紹生成過程剖面圖編輯保存、導出剖面圖實驗數據下載效果預覽 數據分析 本實例使用到的原始數據為案例提供的規則格網DEM

[轉]javaandroid線程池

java多線程-概念&創建啟動&中斷&守護線程&優先級&線程狀態&#xff08;多線程編程之一&#xff09;java多線程同步以及線程間通信詳解&消費者生產者模式&死鎖&Thread.join()&#xff08;多線程編程之二&#xff09;java&android線程池-Exe…

C#實現清理系統內存

金山內存整理工具、360內存清理工具非常好用&#xff0c;可以將系統內存最小化&#xff0c;提升系統運行速度。其實這些事情C#也可以做到&#xff0c;原理就是對系統進程中的進程內存進行逐個優化。 網上大多推薦使用系統的SetProcessWorkingSetSize的函數API&#xff0c;但是經…

C語言試題168之獲取矩陣的最大值及其下標

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:要求使用…

.Net下極限生產力之efcore分表分庫全自動化遷移CodeFirst

開始本次我們的主題就是極限生產力,其他語言望塵莫及的分表分庫全自動化Migrations Code-First 加 efcore 分表分庫無感開發還記得上次發布博客還是在上次,上次發布了如何兼容WTM框架后也有不少小伙伴來問我如何兼容如何遷移等問題,經過這么多框架的兼容我自己也認識到了一些問…

Hadoop日常管理與維護

本文描述了hadoop、hbase的啟動關閉、表操作以及權限管理。一、Hadoop服務的啟動與關閉1、啟動使用hadoop以及hbase自帶的腳本進行啟動&#xff0c;先啟動hadoop個服務&#xff0c;再啟動hbase服務。 hadoopbdi:~$ start-dfs.sh hadoopbdi:~$ start-yarn.sh hadoopbdi:~$ start…

Mathematica修改默認字體

1. 打開Option Inspector 2. 第一個下拉框選擇Global Preference, 搜索stylehints 3. 修改字體為想要換的字體FamilyName, 比如換成蘋果黑體 SimHei, 字體FamilyName自行研究 4. 效果 轉載于:https://www.cnblogs.com/dabaopku/p/6221960.html

基于JavaScript 數組的經典程序應用源碼(強烈建議收藏)

文章目錄設計一個數組輸入并顯示的程序。數組輸入和顯示選擇排序選擇排序排序程序包排序網頁楊輝三角形楊輝三角形網頁C語言畫一個sin(x)的曲線螺旋線訪問二維數組JavaScript數組的定義、使用都是非常簡單的&#xff0c;僅僅定義的話&#xff0c;就使用&#xff1a; var anew …

C語言試題169之誰家孩子跑得最慢

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:張、王、…

【ArcGIS微課1000例】0008:ArcGIS中如何設置相對路徑?(解決圖層前紅色的感嘆號)

文章目錄 問題舉例問題分析解決辦法問題舉例 我們在使用ArcGIS時經常會碰到這樣的問題:將地圖文檔(.mxd)保存到本地并拷貝到別的電腦上或改變一個路徑時,出現數據丟失的現象,具體表現為圖層前面出現一個紅色的感嘆號,如下圖所示。 出現以上問題的根本原因是數據GSS.tif的…

IPC-----消息隊列

消息隊列&#xff08;報文隊列&#xff09;:兩個進程間通過發送數據塊的形式進行通信。一個進程把需要發送的消息通過一個函數發送到消息隊列中&#xff0c;另一個進程再從消息隊列中讀取該消息。函數&#xff1a;# include <sys/types.h># include <sys/ipc.h>key…

[轉]OKR結合CFR的管理模式

讀前預 無論任何管理書籍&#xff0c;都是圍繞著人性&#xff0c;如果激發員工的人性中的自尊和自我價值觀、自我成就感。 作為一名領導者&#xff0c;在管理前&#xff0c;必須要是冷靜&#xff0c;安靜的對待他人 約翰杜爾為谷歌送上大禮 “好主意”再加上”卓越的執行”&…