<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    Golang分析內(nèi)存溢出

    共 2905字,需瀏覽 6分鐘

     ·

    2022-04-12 06:02

    這里是Z哥的個(gè)人公眾號(hào)

    每周五11:45 按時(shí)送達(dá)

    當(dāng)然了,也會(huì)時(shí)不時(shí)加個(gè)餐~

    我的第「223」篇原創(chuàng)敬上



    大家好,我是Z哥。

    最近系統(tǒng)在壓測(cè)過程中發(fā)現(xiàn)有一個(gè)程序在壓力增大后會(huì)內(nèi)存溢出。正好之前自己對(duì) Golang 里分析 dump 這塊還沒怎么涉及,借此契機(jī)學(xué)習(xí)一下。

    網(wǎng)上搜了很多資料,發(fā)現(xiàn) Golang 好像沒有手動(dòng)創(chuàng)建 dump 文件的方式(像 Java 的 jmap,.Net 的創(chuàng)建轉(zhuǎn)儲(chǔ)文件這種)。

    要么通過設(shè)置環(huán)境變量,在程序 crash 的時(shí)候自動(dòng)創(chuàng)建 dump 文件,要么程序里 import 一個(gè) pprof 的 package,實(shí)時(shí)分析 dump 相關(guān)的信息。

    如果有哪位老司機(jī)知道手動(dòng)創(chuàng)建 dump 的方式,請(qǐng)?jiān)谠u(píng)論區(qū)教下大家,感謝~

    下面我手把手教大家如何通過以上兩種方式來(lái)分析內(nèi)存溢出問題,步驟詳細(xì),包教包會(huì),建議收藏~


    /01? 通過 pprof 實(shí)時(shí)分析/

    pprof 全稱是 performance profiles,是 google 官方提供的性能分析工具,項(xiàng)目地址:https://github.com/google/pprof。配合 Graphviz 使用可以提供圖形化的能力。

    使用它的方式很簡(jiǎn)單,配合 pprof 庫(kù)來(lái)使用。只要在代碼里增加兩塊代碼。一塊是 import:

    _ "net/http/pprof"
    另一塊是main函數(shù)的開頭部分


    go func() {    http.ListenAndServe("0.0.0.0:8899", nil)  //ip和端口可以更換}()


    然后就可以在瀏覽器里輸入 http://localhost:8899/debug/pprof/ 看到相關(guān)的性能維度


    上圖中框出的這 4 個(gè)部分應(yīng)該是平時(shí)最常用的,從上往下分別是:

    1. 阻塞分析。比如,goroutine 的 wait。

    2. 內(nèi)存分析。比如,內(nèi)存泄漏、內(nèi)存消耗異常等情況。

    3. 互斥鎖分析。比如,觀察代碼里用到的 sync.RWMutex 和 sync.Mutex 的具體情況。

    4. CPU 分析。比如,排查哪些代碼較多地占用了 CPU 資源。


    雖然直接在瀏覽器頁(yè)面上也能看到一些信息,但是用來(lái)分析是不夠的,想要真正能分析問題還得通過前面提到的 pprof 工具。

    使用 go tool pprof 分析數(shù)據(jù),有兩種方式:

    • 通過url。go tool pprof ?http://localhost:8899/debug/pprof/profile

    • 通過文件。go tool pprof cpuprofile ?文件路徑



    好了,我們來(lái)試一下。

    Z哥寫了一段消耗內(nèi)存的代碼,如下:
    func main() {  go func() {    http.ListenAndServe("0.0.0.0:8899", nil)  }()??  str := "sadasdasffrgrgrgrgrgrfefafasfsadasdasffrgrgrgrgrgrfefafasfsadasdasffrgrgrgrgrgrfefafasfsadasdasffrgrgrgrgrgrfefafasfsadasdasffrgrgrgrgrgrfefafasfsadasdasffrgrgrgrgrgrfefafasf"  for i := 0; i < 999; i++ {    str += str  }??  fmt.Scanln()}

    在 web 頁(yè)面點(diǎn)擊「heap」入口,我們可以看到實(shí)時(shí)內(nèi)存的使用情況。


    然后我們?cè)偻ㄟ^以下命令進(jìn)入到命令交互模式看看效果:

    go tool pprof http://localhost:8899/debug/pprof/heap

    進(jìn)去之后輸入「top」,就能很直觀的看到哪個(gè)方法占用了內(nèi)存。


    這里的幾個(gè)列的含義簡(jiǎn)單羅列下:

    1. flat:當(dāng)前函數(shù)所占用的容量。

    2. flat%:當(dāng)前函數(shù)所占用的容量,在總分配容量的百分比。

    3. sum%:是從調(diào)用的最外層到當(dāng)前方法累加使用的容量占總?cè)萘康陌俜直?/span>

    4. cum:當(dāng)前函數(shù)以及子函數(shù)所占用的容量。

    5. cum%:當(dāng)前函數(shù)以及子函數(shù)所占用的容量,在總分配容量的百分比。

    6. 最后一列是函數(shù)的名字


    我們可以再輸入獲得更詳細(xì)的信息:

    list main.main



    每一行代碼占用了多少容量直接給你羅列出來(lái)了,是不是很香。


    分析其他的也是類似的,比如以下是分析 CPU 的。



    /02 程序 crash 的時(shí)候自動(dòng)創(chuàng)建 dump 文件/
    ?
    大多數(shù)時(shí)候,我們可能沒有條件實(shí)時(shí)分析程序運(yùn)行情況。比如問題在生產(chǎn)環(huán)境偶發(fā)出現(xiàn),且無(wú)法在測(cè)試環(huán)境重現(xiàn)。

    這個(gè)時(shí)候我們可以配置當(dāng)程序 crash 的時(shí)候自動(dòng)保存 dump 文件。

    先輸入命令「ulimit -a」看下當(dāng)前是否開啟了core file。


    如果是0的話說(shuō)明未開啟??梢酝ㄟ^:

    ulimit -c 1024 ?或者 ulimit -c unlimited 來(lái)設(shè)置 dump 文件的最大 size。

    這里的數(shù)字單位是 block,具體需要根據(jù)所在的操作系統(tǒng)一個(gè) block 對(duì)應(yīng)的大小來(lái)設(shè)置。

    如果你想讓這個(gè)設(shè)置永久生效那么需要將它添加到 /.profile 中

    echo "ulimit -c unlimited" >> ~/.profile


    再看下 Golang 的環(huán)境變量 GOTRACEBACK 的設(shè)置是什么,

    export


    如果不是 crash 或者不存在 GOTRACEBACK 的環(huán)境變量(默認(rèn)是 none)的話,改成 crash。

    export GOBACTRACE=crash


    這就意味著,讓程序發(fā)生 crash 的時(shí)候會(huì)自動(dòng)生成 dump 文件。(Z哥在 mac 系統(tǒng)上運(yùn)行沒能自動(dòng)生成 dump 文件,但在 centos 上可以)

    然后運(yùn)行的程序如果發(fā)生 panic,會(huì)自動(dòng)生成 dump 文件在程序運(yùn)行的目錄下。


    紅框圈出來(lái)的是它的默認(rèn)文件名的格式。

    同unlimited 一樣,也需要讓這個(gè)設(shè)置永久生效的話,需要添加到/.profile中

    echo "export GOTRACEBACK=crash " >> ~/.profile


    有了 dump 文件,你就可以用 gdb 或者 delve 工具來(lái)分析了(官方更建議我們使用 delve,對(duì) Golang 的支持更好,這里就先不展開了。

    一般來(lái)說(shuō),建議大家如果在本地環(huán)境的話使用 pprof 就好了,如果在服務(wù)器上,務(wù)必開始 crash 自動(dòng)保存 dump 的功能,便于后續(xù)的快速定位問題并分析。


    好了,這篇呢,Z 哥和你分享了在 Golang 中分析運(yùn)行時(shí)的代碼問題。主要有兩種途徑:

    • 通過 pprof 實(shí)時(shí)分析。

    • 程序 crash 時(shí)自動(dòng)保存 dump,再通過 delve 或者 gdb 分析。


    希望對(duì)你有所幫助。建議收藏,以防不備之需~



    推薦閱讀:


    原創(chuàng)不易,如果你覺得這篇文章還不錯(cuò),就「點(diǎn)贊」或者「在看」一下吧,鼓勵(lì)我的創(chuàng)作 :)


    也可以分享我的公眾號(hào)名片給有需要的朋友們。

    如果你有關(guān)于軟件架構(gòu)、分布式系統(tǒng)、產(chǎn)品、運(yùn)營(yíng)的困惑

    可以試試點(diǎn)擊「閱讀原文

    瀏覽 103
    點(diǎn)贊
    評(píng)論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)
    評(píng)論
    圖片
    表情
    推薦
    點(diǎn)贊
    評(píng)論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    青青青青青青久久久久久久 | 欧洲一级黄色A片 | 操b免费网站 | 国产三区视频 | 77777777少妇亚洲 |