最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang使用pprof檢查內(nèi)存泄漏的全過程

 更新時間:2024年02月04日 09:35:33   作者:hankeyyh  
pprof 是golang提供的一款分析工具,可以分析CPU,內(nèi)存的使用情況,本篇文章關(guān)注它在分析內(nèi)存泄漏方面的應(yīng)用,本文給大家介紹了Golang使用pprof檢查內(nèi)存泄漏的全過程,文中通過代碼給大家介紹的非常詳細,需要的朋友可以參考下

前言

pprof 是golang提供的一款分析工具,可以分析CPU,內(nèi)存的使用情況,本篇文章關(guān)注它在分析內(nèi)存泄漏方面的應(yīng)用。pprof 不能直觀顯示出某個函數(shù)發(fā)生了泄漏,它的用途是列出當前內(nèi)存分配較大的位置,通過比較一段時間pprof的結(jié)果,可以發(fā)現(xiàn)內(nèi)存變化。

測試代碼

比如我們有下面的函數(shù),在請求中對全局變量分配了一塊內(nèi)存,但沒有回收:

package main

import (
    "fmt"
    "log"
    "net/http"
    _ "net/http/pprof" // 關(guān)鍵?。?
    "runtime"
    "sync"
)

type UserData struct {
    Data []byte
}

type UserCache struct {
    mu    sync.Mutex
    Cache map[string]*UserData
}

func (uc *UserCache) clear() {
    uc.mu.Lock()
    defer uc.mu.Unlock()
    uc.Cache = make(map[string]*UserData)
}

func NewUserCache() *UserCache {
    return &UserCache{
        Cache: make(map[string]*UserData),
    }
}

var userCache = NewUserCache()

// 分配全局內(nèi)存
func handleRequest(w http.ResponseWriter, r *http.Request) {
    userCache.mu.Lock()
    defer userCache.mu.Unlock()
    
    userData := &UserData{
        Data: make([]byte, 1000000),
    }

    userID := fmt.Sprintf("%d", len(userCache.Cache))
    // 賦值給全局變量,但沒有回收
    userCache.Cache[userID] = userData
    log.Printf("Added data for user %s. Total users: %d\n", userID, len(userCache.Cache))
}

// 清空全局內(nèi)存
func handleClear(w http.ResponseWriter, r *http.Request) {
    userCache.clear()
    runtime.GC()
}

func main() {
    http.HandleFunc("/leaky-endpoint", handleRequest)
    http.HandleFunc("/clear", handleClear)
    
    http.ListenAndServe(":8080", nil)
}

其中 import "net/http/pprof" 引入了pprof工具,啟動服務(wù)后,內(nèi)存分析結(jié)果保存在http://localhost:8080/debug/pprof/heap。

發(fā)送請求

我們往/leaky-endpoint發(fā)送一些請求,觸發(fā)全局內(nèi)存分配,可以使用 ab 命令:

ab -n 1000 -c 10 http://localhost:8080/leaky-endpoint

-n:請求數(shù)量,我們總共發(fā)送1000個請求

-c:并發(fā)數(shù)量,1000個請求通過10個并發(fā)線程發(fā)送

分析內(nèi)存

查看內(nèi)存分配

我們可以通過下面的命令查看分析結(jié)果:

pprof http://localhost:8080/debug/pprof/heap

// output: 
// Entering interactive mode (type "help" for commands, "o" for options)
// (pprof)

輸入上述命令后,會進入命令行交互模式,我們可以輸入一系列幫助命令查看內(nèi)存分析結(jié)果:

  • top:輸出內(nèi)存分配最多的幾個函數(shù)
(pprof) top
Showing nodes accounting for 487.41MB, 100% of 487.41MB total
      flat  flat%   sum%        cum   cum%
  487.41MB   100%   100%   487.41MB   100%  main.handleRequest
         0     0%   100%   487.41MB   100%  net/http.(*ServeMux).ServeHTTP
         0     0%   100%   487.41MB   100%  net/http.(*conn).serve
         0     0%   100%   487.41MB   100%  net/http.HandlerFunc.ServeHTTP
         0     0%   100%   487.41MB   100%  net/http.serverHandler.ServeHTTP

可以看到,handleRequest 分配了最多的內(nèi)存。這幾列的含義是:

  • flat:函數(shù)自身在采樣期間直接消耗的內(nèi)存,不包括它調(diào)用的其他函數(shù)的消耗;
  • flag%: flat 值占總消耗資源的百分比,這個百分比是基于整個程序在采樣期間的資源消耗來計算的;
  • sum%: 累積百分比,表示從輸出列表頂部開始到當前行為止的所有函數(shù)的 flat 百分比之和。這可以幫助你理解最頂部的函數(shù)累積起來消耗了多少資源;
  • cum: 函數(shù)自身flat,加上它調(diào)用的所有函數(shù)在采樣期間消耗的內(nèi)存;
  • cum%: cum 值占總消耗資源的百分比。這個百分比顯示了函數(shù)及其所有遞歸調(diào)用的資源消耗在程序總資源消耗中的比重;
  • list:列出函數(shù)具體分配內(nèi)存的位置
(pprof) list main.handleRequest
Total: 487.41MB
ROUTINE ======================== main.handleRequest in /home/yuhanyang/project/HelloGo/test_mem_leak/main.go
 487.41MB   487.41MB (flat, cum)   100% of Total
        .          .     35:func handleRequest(w http.ResponseWriter, r *http.Request) {
        .          .     36:   userCache.mu.Lock()
        .          .     37:   defer userCache.mu.Unlock()
        .          .     38:
        .          .     39:   userData := &UserData{
 487.41MB   487.41MB     40:           Data: make([]byte, 1000000),
        .          .     41:   }
  • web:在瀏覽器中生成并打開 SVG 格式的調(diào)用圖

  • png:生成 PNG 格式的調(diào)用圖

比較內(nèi)存分配

為了分析內(nèi)存泄漏,我們往往需要統(tǒng)計一段時間開始和結(jié)束時的內(nèi)存變化情況,在上面的基礎(chǔ)上,我們可以再用ab命令觸發(fā)幾次內(nèi)存分配,然后通過pprof查看:

>>pprof  http://localhost:8080/debug/pprof/heap
(pprof) top
Showing nodes accounting for 3.74GB, 100% of 3.74GB total
      flat  flat%   sum%        cum   cum%
    3.74GB   100%   100%     3.74GB   100%  main.handleRequest
         0     0%   100%     3.74GB   100%  net/http.(*ServeMux).ServeHTTP
         0     0%   100%     3.74GB   100%  net/http.(*conn).serve
         0     0%   100%     3.74GB   100%  net/http.HandlerFunc.ServeHTTP
         0     0%   100%     3.74GB   100%  net/http.serverHandler.ServeHTTP

發(fā)現(xiàn)內(nèi)存較之前增長了,實際上我們可以通過 -diff_base 來比較兩次采樣結(jié)果的差異:

// 第一次采樣
pprof http://localhost:8080/debug/pprof/heap > base.out

// 當前采樣
pprof http://localhost:8080/debug/pprof/heap > current.out

// 差異分析
pprof -diff_base=base.out current.out

查看啟動以來的內(nèi)存分配

上面的pprof實際統(tǒng)計的是采樣時刻的內(nèi)存分配情況,我們可以先清空全局內(nèi)存,然后再通過top查看,會發(fā)現(xiàn)不再有輸出了:

curl http://localhost:8080/clear
pprof  http://localhost:8080/debug/pprof/heap
(pprof) top
Showing nodes accounting for 0, 0% of 0 total
      flat  flat%   sum%        cum   cum%

但我們可以通過-sample_index=來控制采樣,對于內(nèi)存分析來說,它有下面幾種取值:

  • inuse_space:默認,表示程序在執(zhí)行時刻正在使用的內(nèi)存量;
  • inuse_objects:程序在執(zhí)行時刻正在使用的對象數(shù)量;
  • alloc_space:程序自啟動以來分配的總內(nèi)存量,不考慮這些內(nèi)存是否已經(jīng)被釋放;
  • alloc_objects:程序自啟動以來分配的總對象數(shù)量,不考慮這些對象是否已經(jīng)被釋放;

我們可以查看程序啟動以來的總內(nèi)存分配數(shù)據(jù):

pprof -sample_index=alloc_space http://localhost:8080/debug/pprof/heap
(pprof) top
Showing nodes accounting for 3842.05MB, 99.44% of 3863.75MB total
Dropped 44 nodes (cum <= 19.32MB)
Showing top 10 nodes out of 14
      flat  flat%   sum%        cum   cum%
 3832.36MB 99.19% 99.19%  3832.86MB 99.20%  main.handleRequest
    9.70MB  0.25% 99.44%    19.36MB   0.5%  compress/flate.NewWriter

以上就是Golang使用pprof檢查內(nèi)存泄漏的全過程的詳細內(nèi)容,更多關(guān)于Golang pprof內(nèi)存泄漏的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • golang反向代理設(shè)置host不生效的問題解決

    golang反向代理設(shè)置host不生效的問題解決

    在使用golang的httputil做反向代理的時候,發(fā)現(xiàn)一個奇怪的現(xiàn)象,上游網(wǎng)關(guān)必須要設(shè)置host才行,不設(shè)置host的話,golang服務(wù)反向代理請求下游會出現(xiàn)http 503錯誤,接下來通過本文給大家介紹golang反向代理設(shè)置host不生效問題,感興趣的朋友一起看看吧
    2023-05-05
  • Go語言中的switch用法實例分析

    Go語言中的switch用法實例分析

    這篇文章主要介紹了Go語言中的switch用法,實例分析了switch的功能及使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • Golang技巧之重試機制詳解

    Golang技巧之重試機制詳解

    重試機制是一種在程序執(zhí)行過程中出現(xiàn)錯誤后重新嘗試執(zhí)行程序的一種機制,可以減少程序運行過程中出現(xiàn)的錯誤,從而提高程序的可靠性,本文就來講講Golang中是如何實現(xiàn)重試機制的吧
    2023-05-05
  • 一文詳解Go語言中的有限狀態(tài)機FSM

    一文詳解Go語言中的有限狀態(tài)機FSM

    有限狀態(tài)機(Finite?State?Machine,F(xiàn)SM)是一種數(shù)學模型,用于描述系統(tǒng)在不同狀態(tài)下的行為和轉(zhuǎn)移條件。本文主要來和大家簡單講講Go語言中的有限狀態(tài)機FSM的使用,需要的可以參考一下
    2023-04-04
  • Golang實現(xiàn)Json分級解析及數(shù)字解析實踐詳解

    Golang實現(xiàn)Json分級解析及數(shù)字解析實踐詳解

    你是否遇到過在無法準確確定json層級關(guān)系的情況下對json進行解析的需求呢?本文就來和大家介紹一次解析不確定的json對象的經(jīng)歷,以及遇到的問題和解決方法
    2023-02-02
  • Golang中http包的具體使用

    Golang中http包的具體使用

    Go語言內(nèi)置的net/http包十分優(yōu)秀,提供了http客戶端和服務(wù)器的實現(xiàn),本文主要介紹了Golang中http包的具體使用,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • Go語言并發(fā)技術(shù)詳解

    Go語言并發(fā)技術(shù)詳解

    這篇文章主要介紹了Go語言并發(fā)技術(shù)詳解,本文講解了goroutine、channels、Buffered Channels、Range和Close等內(nèi)容,需要的朋友可以參考下
    2014-10-10
  • 解析Golang中引用類型是否進行引用傳遞

    解析Golang中引用類型是否進行引用傳遞

    這篇文章主要為大家介紹了Golang中引用類型是否進行引用傳遞剖析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Go語言空白表示符_的實例用法

    Go語言空白表示符_的實例用法

    在本篇內(nèi)容里小編給大家整理的是一篇關(guān)于Go語言空白表示符_的實例用法,有興趣的朋友們可以學習參考下。
    2021-07-07
  • 使用go實現(xiàn)一個超級mini的消息隊列的示例代碼

    使用go實現(xiàn)一個超級mini的消息隊列的示例代碼

    本文主要介紹了使用go實現(xiàn)一個超級mini的消息隊列的示例代碼,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12

最新評論

额尔古纳市| 大厂| 广汉市| 乐清市| 鲁甸县| 儋州市| 清水河县| 海淀区| 南郑县| 丰原市| 正镶白旗| 屯留县| 华宁县| 土默特左旗| 潜山县| 五大连池市| 中宁县| 内江市| 油尖旺区| 抚州市| 云阳县| 桂林市| 南投市| 吉木乃县| 克什克腾旗| 泰安市| 茶陵县| 青神县| 白水县| 巴塘县| 宁远县| 宾川县| 德州市| 成武县| 津市市| 大冶市| 仪征市| 广宁县| 明水县| 曲阳县| 威远县|