国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

記一次 .NET 某游戲服務(wù)后端 內(nèi)存暴漲分析

這篇具有很好參考價(jià)值的文章主要介紹了記一次 .NET 某游戲服務(wù)后端 內(nèi)存暴漲分析。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一:背景

1. 講故事

前幾天有位朋友找到我,說他們公司的后端服務(wù)內(nèi)存暴漲,而且CPU的一個(gè)核也被打滿,讓我?guī)兔聪略趺椿厥?,一般來說內(nèi)存暴漲的問題都比較好解決,就讓朋友抓一個(gè) dump 丟過來,接下來我們用 WinDbg 一探究竟。

二:WinDbg 分析

1. 到底是誰在暴漲

拿到 dump 之后,首先要判斷是托管還是非托管問題,這決定了我們后續(xù)的探究方向,我們直接用 !address -summary + !dumpheap -stat 即可。


0:000> !address -summary

--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE                                212     7dfe`fb4e7000 ( 125.996 TB)           98.43%
MEM_RESERVE                             368      200`1dbd6000 (   2.000 TB)  99.82%    1.56%
MEM_COMMIT                             1741        0`e6f33000 (   3.609 GB)   0.18%    0.00%

0:000> !dumpheap -stat
Statistics:
              MT    Count    TotalSize Class Name
...
7ff9858ad8e0   409,869   258,383,328 System.Collections.Generic.Dictionary<System.Int64, xxx.xxx>+Entry[]
0225cc98e1f0   283,654   479,330,568 Free
7ff9858ab160         8 2,147,484,480 xxx.xxxUnit[]

0:000> !dumpheap -mt 7ff9858ab160
         Address               MT           Size
    022585dd26b8     7ff9858ab160             24 
    02258beb3c78     7ff9858ab160             24 
    02259f272aa8     7ff9858ab160            152 
    0225a8ae0858     7ff9858ab160            152 
    0225a8d015c8     7ff9858ab160            152 
    0225a91da130     7ff9858ab160            152 
    0225a9395ad0     7ff9858ab160            152 
    022694c91020     7ff9858ab160  2,147,483,672 

Statistics:
          MT Count     TotalSize Class Name
7ff9858ab160     8 2,147,484,480 xxx.xxxUnit[]
Total 8 objects, 2,147,484,480 bytes

從卦象看,3.6G 的提交內(nèi)存,xxx.xxxUnit[] 就占用了 2.1G,可以確定當(dāng)前是托管內(nèi)存暴漲,并且也看到了內(nèi)存都被 022694c91020 這個(gè)對象給吃掉了,接下來就是看下這個(gè)對象到底被誰持有著? 使用 !gcroot 即可。


0:000> !gcroot 022694c91020  
Caching GC roots, this may take a while.
Subsequent runs of this command will be faster.

Found 0 unique roots.

我去,從卦中看當(dāng)前的 022694c91020 沒有引用根,也就表明這個(gè)對象應(yīng)該會在后續(xù)過程中被回收,但這里有一個(gè)問題,這個(gè) xxx.xxxUnit[] 到底定義在代碼何處呢? 知道在何處,就可以完美的解決問題。

2. 數(shù)組到底定義在何處

可以仔細(xì)想一想,xxx.xxxUnit[] 沒有被 GC 回收,從側(cè)面也表明它可能剛分配不久,并且是一個(gè)局部變量,既然是局部變量,就可以反向找到是哪一個(gè)線程分配的,如果線程棧還殘留著 返回地址 信息,就可以反推出是哪一個(gè)方法,有了這個(gè)思路,接下來就可以動(dòng)手挖了。

按照編碼人的習(xí)慣, xxx.xxxUnit[] 肯定是某一個(gè) List<xxxUnit> 集合,可以用內(nèi)存搜索解決。


0:000> s-q 0 L?0xffffffffffffffff 022694c91020
00000225`a89530a0  00000226`94c91020 0cca3690`0cca3690

0:000> !lno 00000225`a89530a0
Before:  00000225a8953098           32 (0x20)	System.Collections.Generic.List`1[[xxx.xxxUnit, xx.xx]]
After:   00000225a89530b8         1224 (0x4c8)	Free
Heap local consistency confirmed.

從卦中看,果然用的是一個(gè) List<xxx.xxxUnit> 集合,萬事開頭難,接下來繼續(xù)反向搜索,如果線程棧還有殘留的話,就可以找到它所屬的線程棧。


0:000> s-q 0 L?0xffffffffffffffff 00000225a8953098
0000004c`417ecd98  00000225`a8953098 00000005`00000000
0000004c`417eceb8  00000225`a8953098 0cca3695`00000000
00000225`f1070180  00000225`a8953098 00000225`d7d287f8
00000225`f10701e0  00000225`a8953098 00000225`d7d287f8

0:000> !address 0000004c`417ecd98

Usage:                  Stack
Base Address:           0000004c`417d1000
End Address:            0000004c`417f0000
Region Size:            00000000`0001f000 ( 124.000 kB)
State:                  00001000          MEM_COMMIT
Protect:                00000004          PAGE_READWRITE
Type:                   00020000          MEM_PRIVATE
Allocation Base:        0000004c`41670000
Allocation Protect:     00000004          PAGE_READWRITE
More info:              ~0k


Content source: 1 (target), length: 3268

從卦中的 More info: 信息來看,它是屬于 0 號線程,如果你不相信的話,可以拿 417d1000 去內(nèi)存段驗(yàn)證下,輸出如下:


0:000> !address -f:Stack

        BaseAddress      EndAddress+1        RegionSize     Type       State                 Protect             Usage
--------------------------------------------------------------------------------------------------------------------------
      4c`41670000       4c`417cc000        0`0015c000 MEM_PRIVATE MEM_RESERVE                                    Stack      [~0; ec8.1584]
      4c`417cc000       4c`417d1000        0`00005000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE | PAGE_GUARD        Stack      [~0; ec8.1584]
      4c`417d1000       4c`417f0000        0`0001f000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     Stack      [~0; ec8.1584]

既然找到了是 0 號線程,接下來可以用 !clrstack 觀察下,奇怪的是 0 號線程啥都沒有,我懷疑這個(gè) dump 抓的有問題,可以截圖為證。

記一次 .NET 某游戲服務(wù)后端 內(nèi)存暴漲分析

看不到任何線程棧信息,這就難搞了,接下來的路在何方呢?

3. 還有希望嗎

作為調(diào)試人,一定要在絕望中尋找希望,突破口就是考驗(yàn)線程棧布局的理解,可以在棧上往小地址找,會找到子函數(shù)的返回地址(returnAddress),即類似的格式: 0x00007ffxxxxxx,這個(gè)地址和 List<xxx.xxxUnit> 都同屬一個(gè)方法,如果不清楚的話畫個(gè)簡圖如下:

記一次 .NET 某游戲服務(wù)后端 內(nèi)存暴漲分析

如圖中所述找到 子方法 ReturnAddress 地址值即可,接下來使用windbg 的 dqs 命令外加 !ip2md 觀察方法名即可。


0:000> dqs 0000004c`417ecd98 L-50
0000004c`417ecb18  0000004c`417ed678
0000004c`417ecb20  00000225`b9e78518
0000004c`417ecb28  00007ff9`85f3f861
0000004c`417ecb30  00000225`ba22b8c0
0000004c`417ecb38  0000001a`00000027
0000004c`417ecb40  00000225`00000027
0000004c`417ecb48  00000225`84aef0f8
...
0000004c`417ecd88  0000001a`00000000
0000004c`417ecd90  00000225`82278a68

0:000> !ip2md 00007ff9`85f3f861
MethodDesc:   00007ff983ef1af0
Method Name:          xxx.xxx.xxxRange(xxx,xxx,xxx,xxx)
Class:                00007ff983ef1a58
MethodTable:          00007ff983ef1b70
mdToken:              0000000006000A47
Module:               00007ff983d9c060
IsJitted:             yes
Current CodeAddr:     00007ff985f3f160
Version History:
  ILCodeVersion:      0000000000000000
  ReJIT ID:           0
  IL Addr:            00000225ef226c48
     CodeAddr:           00007ff985f3f160  (MinOptJitted)
     NativeCodeVersion:  0000000000000000

在卦中獲取到這些信息之后,接下來看下 xxx.xxx.xxxRange 中是否有 List<xxxUnit> 集合,為什么高達(dá) 2個(gè)G,經(jīng)過仔細(xì)研讀代碼,終于發(fā)現(xiàn)了問題,截圖如下:

記一次 .NET 某游戲服務(wù)后端 內(nèi)存暴漲分析

從圖中看,核心點(diǎn)就是這里的 num++,在某些情況下會導(dǎo)致在 for 中出不來繼而不斷的 List.Add ,最終導(dǎo)致問題的發(fā)生。

再回頭結(jié)合朋友說的內(nèi)存暴漲,伴隨一個(gè) CPU 核心被打滿,完全就可以解釋了。

三:總結(jié)

這是一個(gè)比較隱晦的邏輯bug導(dǎo)致的內(nèi)存暴漲,如果僅僅從代碼層面去分析,相信你可能要花費(fèi)好久的時(shí)間,從高級調(diào)試的角度看,在 List 無根的情況下如何快速的找到 List 所屬的代碼塊,也是對基礎(chǔ)知識的一個(gè)考驗(yàn)。
記一次 .NET 某游戲服務(wù)后端 內(nèi)存暴漲分析文章來源地址http://www.zghlxwxcb.cn/news/detail-554357.html

到了這里,關(guān)于記一次 .NET 某游戲服務(wù)后端 內(nèi)存暴漲分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 記一次 .NET某游戲后端API服務(wù) CPU爆高分析

    記一次 .NET某游戲后端API服務(wù) CPU爆高分析

    前幾天有位朋友找到我,說他們的API服務(wù)程序跑著跑著CPU滿了降不下去,讓我?guī)兔聪略趺椿厥?,現(xiàn)在貌似民間只有我一個(gè)人專注dump分析,還是申明一下我dump分析是免費(fèi)的,如果想學(xué)習(xí).NET高級調(diào)試的分析技術(shù),可以來我的訓(xùn)練營看看,話不多說,dump分析走起! 昨天錄了一

    2024年03月21日
    瀏覽(27)
  • 記一次 .NET某道閘收費(fèi)系統(tǒng) 內(nèi)存溢出分析

    記一次 .NET某道閘收費(fèi)系統(tǒng) 內(nèi)存溢出分析

    前些天有位朋友找到我,說他的程序幾天內(nèi)存就要爆一次,不知道咋回事,找不出原因,讓我?guī)兔匆幌?,這種問題分析dump是最簡單粗暴了,拿到dump后接下來就是一頓分析。 程序既然會爆,可能是虛擬地址受限,也可能是系統(tǒng)內(nèi)存不足,可以用 !address -summary 觀察下。 從卦

    2024年01月18日
    瀏覽(20)
  • 記一次 .NET某培訓(xùn)學(xué)校系統(tǒng) 內(nèi)存碎片化分析

    記一次 .NET某培訓(xùn)學(xué)校系統(tǒng) 內(nèi)存碎片化分析

    前些天有位朋友微信上找到我,說他們學(xué)校的Web系統(tǒng)內(nèi)存一直下不去,讓我看下到底是怎么回事,老規(guī)矩讓朋友生成一個(gè)dump文件丟給我,看一下便知。 要想看托管還是非托管,可以用 !address -summary 觀察下內(nèi)存段。 從卦中信息的 MEM_COMMIT 和 Heap 來看,應(yīng)該就是托管內(nèi)存的問題

    2024年02月14日
    瀏覽(18)
  • 記一次 Windows10 內(nèi)存壓縮模塊 崩潰分析

    記一次 Windows10 內(nèi)存壓縮模塊 崩潰分析

    在給各位朋友免費(fèi)分析 .NET程序 各種故障的同時(shí),往往也會收到各種其他類型的dump,比如:Windows 崩潰,C++ 崩潰,Mono 崩潰,真的是啥都有,由于基礎(chǔ)知識的相對缺乏,分析起來并不是那么的順利,今天就聊一個(gè) Windows 崩潰的內(nèi)核dump 吧,這個(gè) dump 是前幾天有位朋友給到我的

    2023年04月26日
    瀏覽(28)
  • 記一次 .NET某防偽驗(yàn)證系統(tǒng) 崩潰分析

    記一次 .NET某防偽驗(yàn)證系統(tǒng) 崩潰分析

    昨晚給訓(xùn)練營里面的一位朋友分析了一個(gè)程序崩潰的故障,因?yàn)榭葱』镒幼蛱煸谌豪飭柫艘惶煲矝]搞定,干脆自己親自上陣吧,抓取的dump也是我極力推薦的用 procdump 注冊 AEDebug 的方式,省去了很多溝通成本。 windbg有一個(gè)非常強(qiáng)大的點(diǎn)就是當(dāng)你雙擊打開后,會自動(dòng)幫你切換到

    2024年03月28日
    瀏覽(26)
  • 記一次 .NET 某企業(yè)采購平臺 崩潰分析

    記一次 .NET 某企業(yè)采購平臺 崩潰分析

    前段時(shí)間有個(gè)朋友找到我,說他們的程序有偶發(fā)崩潰的情況,讓我?guī)兔聪略趺椿厥?,針對這種 crash 的程序,用 AEDebug 的方式抓取一個(gè)便知,有了 dump 之后接下來就可以分析了。 既然是程序的崩潰,我們可以像看藍(lán)屏一下看dump文件,使用 !analyze -v 命令即可。 從上面的信息

    2024年02月11日
    瀏覽(24)
  • 記一次 .NET 某企業(yè)內(nèi)部系統(tǒng) 崩潰分析

    記一次 .NET 某企業(yè)內(nèi)部系統(tǒng) 崩潰分析

    前些天有位朋友找到我,說他的程序跑著跑著就崩潰了,讓我看下怎么回事,其實(shí)沒怎么回事,抓它的 crash dump 就好,具體怎么抓也是被問到的一個(gè)高頻問題,這里再補(bǔ)一下鏈接: [.NET程序崩潰了怎么抓 Dump ? 我總結(jié)了三種方案] https://www.cnblogs.com/huangxincheng/p/14811953.html ,采用

    2024年02月10日
    瀏覽(22)
  • 記一次 .NET 某券商論壇系統(tǒng) 卡死分析

    記一次 .NET 某券商論壇系統(tǒng) 卡死分析

    前幾個(gè)月有位朋友找到我,說他們的的web程序沒有響應(yīng)了,而且監(jiān)控發(fā)現(xiàn)線程數(shù)特別高,內(nèi)存也特別大,讓我?guī)兔匆幌略趺椿厥?,現(xiàn)在回過頭來幾經(jīng)波折,回味價(jià)值太濃了。 這個(gè)程序內(nèi)存高,線程高,無響應(yīng),尼瑪是一個(gè)復(fù)合態(tài)問題,那怎么入手呢?按經(jīng)驗(yàn)推測,大概率是

    2024年02月05日
    瀏覽(32)
  • 記一次 .NET 某醫(yī)院門診軟件 卡死分析

    記一次 .NET 某醫(yī)院門診軟件 卡死分析

    前幾天有位朋友找到我,說他們的軟件在客戶那邊卡死了,讓我?guī)兔聪率窃趺椿厥??我就讓朋友在程序卡死的時(shí)候通過 任務(wù)管理器 抓一個(gè) dump 下來,雖然默認(rèn)抓的是 wow64 ,不過用 soswow64.dll 轉(zhuǎn)還是可以的,參考命令如下: 接下來就可以分析了哈。 首先用 !t 簡單看一下主

    2024年02月04日
    瀏覽(19)
  • 記一次 .NET某賬本軟件 非托管泄露分析

    記一次 .NET某賬本軟件 非托管泄露分析

    中秋國慶長假結(jié)束,哈哈,在老家拍了很多的短視頻,有興趣的可以上B站觀看:https://space.bilibili.com/409524162 ,今天繼續(xù)給大家分享各種奇奇怪怪的.NET生產(chǎn)事故,希望能幫助大家在未來的編程之路上少踩坑。 話不多說,這篇看一個(gè) .NET程序集泄露 導(dǎo)致的CLR私有堆泄露的案例,

    2024年02月08日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包