Golang程序如何查找內(nèi)存泄漏(pprof)
Golang程序查找內(nèi)存泄漏
1. 在main包中
選擇在一個(gè)單獨(dú)文件中加上pprof包引用并設(shè)置條件編譯,這樣不會(huì)與develop正式版本代碼產(chǎn)生任何耦合。
// +build debug package main import ( "net/http" _ "net/http/pprof" ) func init() { go http.ListenAndServe(":18080", nil) }
2. 編譯
go build -tags debug .
3. 在目標(biāo)機(jī)中運(yùn)行剛編譯出來的debug版本程序
本例中ip為隨意編寫的。
4. 執(zhí)行
go tool pprof -inuse_space http://192.168.20.5:18080/debug/pprof/heap進(jìn)入交互模式:
[user@LAPTOP-LCP testtool]$ go tool pprof -inuse_space http://192.168.20.5:18080/debug/pprof/heap Fetching profile over HTTP from http://192.168.20.5:18080/debug/pprof/heap Saved profile in C:\Users\Noname\pprof\pprof.testtool.alloc_objects.alloc_space.inuse_objects.inuse_space.006.p b.gz File: testtool Type: inuse_space Time: Aug 16, 2022 at 2:24pm (CST) Entering interactive mode (type "help" for commands, "o" for options) (pprof) top 10 Showing nodes accounting for 27831.78kB, 100% of 27831.78kB total Showing top 10 nodes out of 35 flat flat% sum% cum cum% 11787.50kB 42.35% 42.35% 11787.50kB 42.35% runtime.allocm 9382.95kB 33.71% 76.07% 9382.95kB 33.71% io.ReadAll 2561.02kB 9.20% 85.27% 2561.02kB 9.20% runtime.malg 1536.21kB 5.52% 90.79% 1536.21kB 5.52% github.com/aws/aws-sdk-go/aws/endpoints.init 514kB 1.85% 92.63% 514kB 1.85% bufio.NewReaderSize 514kB 1.85% 94.48% 514kB 1.85% bufio.NewWriterSize 512.08kB 1.84% 96.32% 512.08kB 1.84% net/http.newTransferWriter 512.02kB 1.84% 98.16% 512.02kB 1.84% runtime.gcBgMarkWorker 512kB 1.84% 100% 512kB 1.84% runtime.doaddtimer 0 0% 100% 9382.95kB 33.71% io/ioutil.ReadAll (pprof) (pprof)
交互界面使用top命令查看內(nèi)存分配最多的函數(shù)。
如果本機(jī)中有源代碼,可以使用list命令查看源代碼中哪一行分配的函數(shù)最多。
(pprof) (pprof) list io.ReadAll Total: 27.18MB ROUTINE ======================== io.ReadAll in C:\Program Files\Go\src\io\io.go 9.16MB 9.16MB (flat, cum) 33.71% of Total . . 626:func ReadAll(r Reader) ([]byte, error) { . . 627: b := make([]byte, 0, 512) . . 628: for { . . 629: if len(b) == cap(b) { . . 630: // Add more capacity (let append pick how much). 9.16MB 9.16MB 631: b = append(b, 0)[:len(b)] . . 632: } . . 633: n, err := r.Read(b[len(b):cap(b)]) . . 634: b = b[:len(b)+n] . . 635: if err != nil { . . 636: if err == EOF { (pprof) (pprof)
5. 也可以使用以下命令直接導(dǎo)出調(diào)用圖
非常直觀(需要安裝Graphviz,詳詢Download | Graphviz)
go tool pprof -inuse_space -png http://192.168.20.5:18080/debug/pprof/heap > heap.png
可以在圖片中直觀地看到,調(diào)用過程中每個(gè)函數(shù)的內(nèi)存使用占比。
出現(xiàn)內(nèi)存泄漏時(shí),如果只查看一次很難確定真正出現(xiàn)內(nèi)存泄露的代碼位置,可以在程序運(yùn)行一段時(shí)間后,程序出現(xiàn)內(nèi)存泄露已經(jīng)很明顯后,再次查看內(nèi)存占用分析圖,找到兩張圖中內(nèi)存占用比例相差最大的函數(shù)。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Golang使用gob實(shí)現(xiàn)結(jié)構(gòu)體的序列化過程詳解
Golang struct類型數(shù)據(jù)序列化用于網(wǎng)絡(luò)傳輸數(shù)據(jù)或在磁盤上寫入數(shù)據(jù)。在分布式系統(tǒng)中,一端生成數(shù)據(jù)、然后序列化、壓縮和發(fā)送;在另一端,接收數(shù)據(jù)、然后解壓縮、反序列化和處理數(shù)據(jù),整個(gè)過程必須快速有效2023-03-03gorm整合進(jìn)go-zero的實(shí)現(xiàn)方法
go-zero提供的代碼生成器里面,沒有提供orm框架操作,但是提供了遍歷的緩存操作,所以可以利用gorm當(dāng)作一個(gè)sql語(yǔ)句的生成器,把生成后的sql語(yǔ)句放到go-zero生成的模板中去執(zhí)行,對(duì)gorm整合進(jìn)go-zero的實(shí)現(xiàn)方法感興趣的朋友一起看看吧2022-03-03Golang的循環(huán)中break和continue語(yǔ)句的用法講解
這篇文章主要介紹了Golang的循環(huán)中break和continue語(yǔ)句的用法講解,是Go語(yǔ)言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-10-10基于go語(yǔ)言實(shí)現(xiàn)圖片驗(yàn)證碼的代碼示例
這篇文章主要為大家詳細(xì)介紹了基于go語(yǔ)言實(shí)現(xiàn)圖片驗(yàn)證碼的代碼示例,文中的示例代碼簡(jiǎn)潔易懂,具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10Go語(yǔ)言并發(fā)之context標(biāo)準(zhǔn)庫(kù)的使用詳解
Context的出現(xiàn)是為了解決在大型應(yīng)用程序中的并發(fā)環(huán)境下,協(xié)調(diào)和管理多個(gè)goroutine之間的通信、超時(shí)和取消操作的問題,本文就來和大家簡(jiǎn)單聊聊它的具體用法,希望對(duì)大家有所幫助2023-06-06Go語(yǔ)言中結(jié)構(gòu)體方法副本傳參與指針傳參的區(qū)別介紹
這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言中結(jié)構(gòu)體方法副本傳參與指針傳參的區(qū)別的相關(guān)資料,文中先對(duì)GO語(yǔ)言結(jié)構(gòu)體方法跟結(jié)構(gòu)體指針方法的區(qū)別進(jìn)行了一些簡(jiǎn)單的介紹,來幫助大家理解學(xué)習(xí),需要的朋友可以參考下。2017-12-12通過函數(shù)如何將golang?float64?保留2位小數(shù)(方法匯總)
這篇文章主要介紹了通過函數(shù)將golang?float64保留2位小數(shù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08