<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 2905字,需瀏覽 6分鐘

           ·

          2022-04-12 06:02

          這里是Z哥的個人公眾號

          每周五11:45 按時送達

          當然了,也會時不時加個餐~

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



          大家好,我是Z哥。

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

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

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

          如果有哪位老司機知道手動創(chuàng)建 dump 的方式,請在評論區(qū)教下大家,感謝~

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


          /01? 通過 pprof 實時分析/

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

          使用它的方式很簡單,配合 pprof 庫來使用。只要在代碼里增加兩塊代碼。一塊是 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 個部分應(yīng)該是平時最常用的,從上往下分別是:

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

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

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

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


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

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

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

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



          好了,我們來試一下。

          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 頁面點擊「heap」入口,我們可以看到實時內(nèi)存的使用情況。


          然后我們再通過以下命令進入到命令交互模式看看效果:

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

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


          這里的幾個列的含義簡單羅列下:

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

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

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

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

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

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


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

          list main.main



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


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



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

          這個時候我們可以配置當程序 crash 的時候自動保存 dump 文件。

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


          如果是0的話說明未開啟。可以通過:

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

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

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

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


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

          export


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

          export GOBACTRACE=crash


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

          然后運行的程序如果發(fā)生 panic,會自動生成 dump 文件在程序運行的目錄下。


          紅框圈出來的是它的默認文件名的格式。

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

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


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

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


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

          • 通過 pprof 實時分析。

          • 程序 crash 時自動保存 dump,再通過 delve 或者 gdb 分析。


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



          推薦閱讀:


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


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

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

          可以試試點擊「閱讀原文

          瀏覽 103
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天日天天弄 | 蜜乳在线 | 三级久久电影 | 欧洲在线人人操人人爱 | 色色色 婷|