欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang使用pprof和trace進(jìn)行診斷和修復(fù)性能問題

 更新時(shí)間:2024年01月16日 08:31:17   作者:eleven26  
在?Go?中,開發(fā)人員可以使用強(qiáng)大的內(nèi)置工具來幫助診斷和修復(fù)性能問題,其中兩個(gè)工具是?pprof?和?trace?包,下面就跟隨小編一起來了解下如何使用pprof和trace進(jìn)行診斷和修復(fù)性能問題吧

軟件開發(fā)嚴(yán)重依賴調(diào)試技術(shù),這對(duì)于有效處理性能問題至關(guān)重要。用戶在遇到程序執(zhí)行緩慢時(shí)會(huì)感到沮喪,這凸顯了通過調(diào)試工具有效識(shí)別和解決潛在問題的重要性。

但是,由于軟件的創(chuàng)建和實(shí)現(xiàn)過程中涉及龐大的代碼庫(kù)或復(fù)雜的系統(tǒng),因此調(diào)試軟件中的性能問題可能很困難。

在 Go 中,開發(fā)人員可以使用強(qiáng)大的內(nèi)置工具來幫助診斷和修復(fù)性能問題。其中兩個(gè)工具是 pprof 和 trace 包。

pprof 包允許您分析和分析 Go 程序的執(zhí)行,而該 trace 包允許您跟蹤和可視化事件和 goroutine 活動(dòng)。當(dāng)這些工具一起使用時(shí),可以幫我們快速定位 Go 程序中導(dǎo)致性能低下的代碼。

了解性能問題

Go 程序或任何軟件應(yīng)用程序中的性能問題都會(huì)對(duì)用戶體驗(yàn)產(chǎn)生重大影響。Go 程序中的性能問題可能由于多種原因而發(fā)生。在本節(jié)中,我們將介紹性能問題的一些最常見原因以及它們?nèi)绾斡绊懴到y(tǒng)。

  • 低效算法:低效算法會(huì)對(duì)性能產(chǎn)生重大影響,尤其是在處理大型數(shù)據(jù)集時(shí)。這些算法會(huì)占用額外的 CPU 周期和內(nèi)存資源,這可能會(huì)降低整個(gè)應(yīng)用程序的速度。比如暴力搜索方法和無(wú)效的排序算法。
  • 阻塞操作:應(yīng)用程序可能偶爾會(huì)等待 I/O 活動(dòng)完成,例如在磁盤上讀取或?qū)懭霐?shù)據(jù)或連接到網(wǎng)絡(luò)。在此過程中,可能會(huì)發(fā)生阻塞操作并導(dǎo)致執(zhí)行延遲,從而導(dǎo)致性能下降。當(dāng)應(yīng)用程序被阻塞時(shí),它無(wú)法執(zhí)行其他有用的任務(wù),從而導(dǎo)致整體性能下降。
  • 內(nèi)存使用率過高:使用大量?jī)?nèi)存的 Go 應(yīng)用可能會(huì)導(dǎo)致性能問題,尤其是在資源不足的系統(tǒng)上。如果應(yīng)用程序消耗的內(nèi)存多于系統(tǒng)的可用內(nèi)存,則系統(tǒng)可能會(huì)開始交換到磁盤,從而大大降低應(yīng)用程序的性能。如果應(yīng)用程序不能有效地管理內(nèi)存,從而導(dǎo)致內(nèi)存泄漏和其他問題,也會(huì)發(fā)生這種情況。

goroutine 泄漏也會(huì)導(dǎo)致內(nèi)存使用率過高。另外,一些中間價(jià)比如 Elasticsearch 等,則建議直接禁用 swap,因?yàn)?swap 會(huì)導(dǎo)致性能下降,取而代之的是給它足夠大的內(nèi)容。

性能低下的應(yīng)用程序會(huì)導(dǎo)致用戶體驗(yàn)差,從而導(dǎo)致用戶流失。為了獲得最佳體驗(yàn),優(yōu)化 Go 應(yīng)用程序至關(guān)重要。

使用 pprof 診斷性能問題

pprof 是 Go 中的一個(gè)內(nèi)置包,它為開發(fā)人員提供了一個(gè)分析工具,用于觀測(cè)他們的 Go 程序如何使用 CPU 和內(nèi)存。然后收集和分析來自此測(cè)量的數(shù)據(jù)。借助 pprof 軟件包,開發(fā)人員可以輕松測(cè)量和識(shí)別消耗比正常情況更多的 CPU 內(nèi)存的函數(shù),以及分配最多內(nèi)存的程序部分。

讓我們假設(shè)一個(gè)轉(zhuǎn)賬 App 使用 Go,并且它具有允許用戶使用二維碼向朋友匯款的功能。更新該功能后,其開發(fā)人員注意到該應(yīng)用程序的運(yùn)行速度比平時(shí)慢得多,40% 的用戶抱怨掃描二維碼時(shí)延遲長(zhǎng)達(dá) 15 秒,有時(shí)付款失敗。為了正確分析問題,開發(fā)團(tuán)隊(duì)可以在用戶掃描二維碼時(shí)使用 pprof 生成 CPU 分析文件。通過分析文件,他們可能會(huì)發(fā)現(xiàn)哪些函數(shù)占用了過多的 CPU 內(nèi)存或哪些算法效率低下。在發(fā)現(xiàn)問題并修復(fù)問題后,他們可以再次測(cè)試和使用 pprof ,以確保性能得到提高,體驗(yàn)更快、更無(wú)縫。

pprof 的 profile 類型

  • CPU:用于分析程序的 CPU 使用情況。衡量函數(shù)如何消耗不同的 CPU 時(shí)間,從而更容易識(shí)別哪些函數(shù)消耗更多時(shí)間,這些就可能是潛在的瓶頸。
  • Memory:用于分析程序的內(nèi)存使用情況。衡量應(yīng)用程序如何使用內(nèi)存以及應(yīng)用程序的哪些部分分配更多內(nèi)存。
  • Block(阻塞):顯示程序阻塞的位置(例如 I/O 或同步原語(yǔ)),從而更容易識(shí)別并發(fā)低下的區(qū)域。
  • Goroutine(協(xié)程):通過返回正在運(yùn)行、阻塞和等待的狀態(tài)的 Goroutine,可以輕松檢測(cè)到并發(fā)低下的區(qū)域。
  • Trace:捕獲程序執(zhí)行期間發(fā)生的事件的詳細(xì)日志,例如 goroutine 創(chuàng)建和銷毀、調(diào)度、網(wǎng)絡(luò)活動(dòng)和阻塞操作。它在詳細(xì)分析應(yīng)用程序的性能時(shí)非常有用。

分析 profile

我們下面以一個(gè)例子來講解一下:

package main

import (
    "fmt"
    "math/rand"
    "os"
    "runtime/pprof"
)

func main() {
    // 創(chuàng)建一個(gè)保存 CPU 分析結(jié)果的文件
    f, err := os.Create("profile.prof")
    if err != nil {
        panic(err)
    }
    defer f.Close()

    // 開始采集 CPU 性能指標(biāo)
    if err := pprof.StartCPUProfile(f); err != nil {
        panic(err)
    }
    defer pprof.StopCPUProfile()

    // 模擬耗 CPU 的操作
    for i := 0; i < 1000000; i++ {
        n := rand.Intn(100)
        _ = square(n)
    }
}

func square(n int) int {
    return n * n
}

在上面的代碼中:

  • main 函數(shù)生成一個(gè)介于 1 和 1000 之間的隨機(jī)數(shù),然后計(jì)算其平方根。
  • pprof.StartCPUProfile(f) 函數(shù)啟動(dòng) CPU 分析,從而創(chuàng)建可以在以后分析的 profile 文件。
  • defer pprof.StopCPUProfile() 語(yǔ)句確保在程序結(jié)束時(shí)停止 CPU 分析,無(wú)論程序是正常終止還是由于錯(cuò)誤。
  • 我們調(diào)用 rand.Intn(100) 1000000 次來模擬 CPU 密集型任務(wù)。

接下來,我們執(zhí)行這個(gè)程序:

go run main.go

程序運(yùn)行結(jié)束后,會(huì)生成一個(gè)名為 profile.pprof 的文件,這個(gè)文件包含了 CPU 分析的數(shù)據(jù)。我們可以使用 go tool pprof 命令來分析這個(gè)文件:

go tool pprof profile.prof

接下來,會(huì)輸出如下內(nèi)容,并進(jìn)入了一個(gè)交互式的命令行:

Type: cpu
Time: Jan 15, 2024 at 5:17pm (CST)
Duration: 205.21ms, Total samples = 10ms ( 4.87%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) 

我們可以接著輸入一些命令,來查看 profile 的數(shù)據(jù):

比如,我們可以輸入 top 來查看最耗 CPU 的函數(shù):

(pprof) top
Showing nodes accounting for 10ms, 100% of 10ms total
      flat  flat%   sum%        cum   cum%
      10ms   100%   100%       10ms   100%  math/rand.(*Rand).Intn
         0     0%   100%       10ms   100%  main.main
         0     0%   100%       10ms   100%  math/rand.Intn (inline)
         0     0%   100%       10ms   100%  runtime.main
(pprof) 

分析內(nèi)存

若要獲取內(nèi)存配置文件,請(qǐng)修改代碼以使用函數(shù) pprof.WriteHeapProfile() 將堆配置文件寫入文件。在生成隨機(jī)數(shù)并計(jì)算其平方后,您需要添加代碼以將內(nèi)存配置文件寫入文件(mem.prof)。您還將添加一個(gè) time.Sleep(5 * time.Second) 調(diào)用,以便有時(shí)間將內(nèi)存配置文件寫入文件。在下面找到代碼的更新版本:

package main

import (
    "fmt"
    "math/rand"
    "os"
    "runtime/pprof"
    "time"
)

func main() {
    // 創(chuàng)建一個(gè)保存 CPU 分析結(jié)果的文件
    cpuProfileFile, err := os.Create("cpu.prof")
    if err != nil {
        panic(err)
    }
    defer cpuProfileFile.Close()

    // 開始采集 CPU 性能指標(biāo)
    if err := pprof.StartCPUProfile(cpuProfileFile); err != nil {
        panic(err)
    }
    defer pprof.StopCPUProfile()

    // 模擬耗 CPU 的操作
    for i := 0; i < 10; i++ {
        n := rand.Intn(100)
        s := square(n)
        fmt.Printf("%d^2 = %d\n", n, s)
    }

    // 創(chuàng)建一個(gè)保存內(nèi)存分析結(jié)果的文件
    memProfileFile, err := os.Create("mem.prof")
    if err != nil {
        panic(err)
    }
    defer memProfileFile.Close()

    // 將內(nèi)存分析結(jié)果寫入文件
    if err := pprof.WriteHeapProfile(memProfileFile); err != nil {
        panic(err)
    }
    fmt.Println("Memory profile written to mem.prof")

    time.Sleep(5 * time.Second)
}

func square(n int) int {
    return n * n
}

輸出:

31^2 = 961
83^2 = 6889
88^2 = 7744
86^2 = 7396
14^2 = 196
99^2 = 9801
42^2 = 1764
29^2 = 841
86^2 = 7396
86^2 = 7396
Memory profile written to mem.prof

運(yùn)行 go run main.go 后,將生成一個(gè) mem.prof 文件。在交互式 shell 中,鍵入 top 以分析程序的內(nèi)存使用情況。若要顯示此交互式 shell,請(qǐng)運(yùn)行以下命令:

go tool pprof mem.prof

要按 CPU 使用率顯示排名靠前的函數(shù),請(qǐng)鍵入 top 命令:

? go tool pprof mem.prof    
Type: inuse_space
Time: Jan 15, 2024 at 5:22pm (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 1.72MB, 100% of 1.72MB total
      flat  flat%   sum%        cum   cum%
    1.72MB   100%   100%     1.72MB   100%  runtime/pprof.StartCPUProfile
         0     0%   100%     1.72MB   100%  main.main
         0     0%   100%     1.72MB   100%  runtime.main
(pprof) 

從上面的示例中可以看出,pprof 可以讓我們很清楚地知道哪些函數(shù)占用了大量的內(nèi)存或者 CPU。因此,通過將 profile 納入開發(fā)過程,可以很容易地主動(dòng)識(shí)別和解決性能問題,從而實(shí)現(xiàn)更快、更高效的應(yīng)用程序。

在第一個(gè)示例中,我們了解了如何使用 pprof 工具創(chuàng)建 CPU 分析文件并對(duì)其進(jìn)行分析。輸出顯示每個(gè)函數(shù)的調(diào)用次數(shù),以及執(zhí)行每個(gè)函數(shù)所花費(fèi)的總時(shí)間。這使我們能夠識(shí)別消耗最多 CPU 時(shí)間的函數(shù),并可能對(duì)其進(jìn)行優(yōu)化。在第二個(gè)示例中,輸出顯示了每個(gè)函數(shù)的內(nèi)存使用情況,包括分配的數(shù)量和分配的字節(jié)數(shù)。這使我們能夠識(shí)別使用過多內(nèi)存的函數(shù),并可能對(duì)其進(jìn)行優(yōu)化以減少內(nèi)存使用。

使用 trace 追蹤

有時(shí),我們需要有關(guān)程序如何運(yùn)行的更多詳細(xì)信息。在這種情況下,trace 包是一個(gè)非常強(qiáng)大和有用的工具。在本節(jié)中,我們將對(duì)其進(jìn)行介紹。

trace 是一種工具,可讓您收集有關(guān)程序運(yùn)行方式的詳細(xì)信息。它對(duì)于理解 goroutine 是如何創(chuàng)建和調(diào)度的、通道的使用方式以及網(wǎng)絡(luò)請(qǐng)求的處理方式等內(nèi)容非常有用。它提供了程序執(zhí)行的時(shí)間線視圖,可用于識(shí)別一段時(shí)間內(nèi)的性能問題和其他類型的錯(cuò)誤。

trace 可以收集有關(guān)程序運(yùn)行時(shí)發(fā)生的各種事件的數(shù)據(jù)。這些事件包括:Goroutine 創(chuàng)建、銷毀、阻塞、取消阻塞、網(wǎng)絡(luò)活動(dòng)和垃圾回收。每個(gè) trace 事件都分配了一個(gè)時(shí)間戳和一個(gè) goroutine ID,允許您查看事件的順序以及它們之間的關(guān)系。

分析 trace 追蹤數(shù)據(jù)

首先,我們將創(chuàng)建一個(gè)新的 go 文件,將其命名為 trace.go。若要生成跟蹤數(shù)據(jù),請(qǐng)導(dǎo)入 runtime/trace 包并在程序開始時(shí)調(diào)用 trace.Start 。若要停止跟蹤收集,請(qǐng)?jiān)诔绦蚪Y(jié)束時(shí)調(diào)用 trace.Stop 。下面是它的樣子:

package main

import (
    "fmt"
    "math/rand"
    "os"
    "runtime/pprof"
    "runtime/trace"
)

func main() {
    // 創(chuàng)建一個(gè)保存 CPU 分析結(jié)果的文件
    f, err := os.Create("profile.prof")
    if err != nil {
        panic(err)
    }
    defer f.Close()

    // 開始采集 CPU 性能指標(biāo)
    if err := pprof.StartCPUProfile(f); err != nil {
        panic(err)
    }
    defer pprof.StopCPUProfile()

    // 創(chuàng)建一個(gè)保存 trace 追蹤結(jié)果的文件
    traceFile, err := os.Create("trace.out")
    if err != nil {
        panic(err)
    }
    defer traceFile.Close()

    if err := trace.Start(traceFile); err != nil {
        panic(err)
    }
    defer trace.Stop()

    // 模擬耗 CPU 的操作
    for i := 0; i < 10; i++ {
        n := rand.Intn(100)
        _ = square(n)
    }
}

func square(n int) int {
    return n * n
}

運(yùn)行以下命令以啟動(dòng)程序:

go run main.go

要分析跟蹤數(shù)據(jù),可以使用 go tool trace 命令,后跟跟蹤文件的名稱:

go tool trace trace.out 

這將啟動(dòng)基于 Web 的跟蹤數(shù)據(jù)可視化,您可以使用它來了解程序的運(yùn)行方式并識(shí)別性能問題。

您還可以查看有關(guān)各種 goroutine 以及各種進(jìn)程如何運(yùn)行的詳細(xì)信息!Trace 是了解各種流事件、goroutine 分析等等的絕佳工具!

分析和修復(fù)性能問題

使用 pprof 和 trace 收集性能數(shù)據(jù)后,下一步是分析數(shù)據(jù)并確定可能的性能問題。

要解釋 pprof 的輸出,首先需要了解可用的各種類型的分析數(shù)據(jù)。最常見的配置文件類型是 CPU 和內(nèi)存配置文件,就像前面引用的示例一樣。通過分析這些配置文件,可以識(shí)別消耗大量資源并可能成為潛在瓶頸的功能。 pprof 還可以生成其他類型的配置文件,例如互斥鎖爭(zhēng)用和阻塞配置文件,這有助于確定同步和阻塞問題。例如,較高的互斥鎖爭(zhēng)用率可能表明多個(gè) goroutine 正在爭(zhēng)用同一個(gè)鎖,這可能導(dǎo)致阻塞和性能不佳。

如前所述,跟蹤數(shù)據(jù)包含有關(guān)應(yīng)用程序行為的更全面的數(shù)據(jù),例如 goroutines、阻塞操作和網(wǎng)絡(luò)流量。跟蹤數(shù)據(jù)分析可用于檢測(cè)延遲源和其他性能問題,例如網(wǎng)絡(luò)延遲過長(zhǎng)或選擇了效率低下的算法。

一旦確定了性能問題,有幾種方法可以優(yōu)化性能。一種常見的策略是通過重用對(duì)象來減少內(nèi)存分配,同時(shí)減少大型數(shù)據(jù)結(jié)構(gòu)的使用。通過減少可分配的內(nèi)存量和垃圾回收量,可以降低 CPU 使用率并提高整體程序性能。

另一種方法是使用異步 I/O 或非阻塞操作來減少阻塞操作,例如文件 I/O 或網(wǎng)絡(luò)通信。這有助于減少程序等待 I/O 操作完成所花費(fèi)的時(shí)間,并提高整體程序吞吐量。

此外,優(yōu)化算法和數(shù)據(jù)結(jié)構(gòu)可以顯著提高性能。通過選擇更有效的算法和數(shù)據(jù)結(jié)構(gòu),可以減少完成操作所需的 CPU 時(shí)間,并提高整體程序性能。

總結(jié)

優(yōu)化 Go 應(yīng)用程序中的性能以確保它們高效且有效地運(yùn)行非常重要。通過這樣做,我們可以改善用戶體驗(yàn),降低運(yùn)行應(yīng)用程序的成本,并提高代碼的整體質(zhì)量。我們可以使用 pprof 和 trace 工具來分析 CPU 和內(nèi)存使用情況,并識(shí)別 Go 應(yīng)用程序中的瓶頸和其他問題。然后,我們可以根據(jù)這些工具的輸出對(duì)代碼進(jìn)行有針對(duì)性的改進(jìn),例如減少內(nèi)存分配、最小化阻塞操作和優(yōu)化算法。分析工具(如 pprof 和 trace )對(duì)于識(shí)別和解決性能問題至關(guān)重要。

以上就是Golang使用pprof和trace進(jìn)行診斷和修復(fù)性能問題的詳細(xì)內(nèi)容,更多關(guān)于Go pprof trace的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • go?sync包中的互斥鎖Mutex和等待組WaitGroup使用詳解

    go?sync包中的互斥鎖Mutex和等待組WaitGroup使用詳解

    這篇文章主要為大家介紹了go?sync包中的互斥鎖Mutex和等待組WaitGroup使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • golang使用tail實(shí)現(xiàn)追蹤文件變更

    golang使用tail實(shí)現(xiàn)追蹤文件變更

    這篇文章主要為大家介紹了golang如何借助 github.com/hpcloud/tail ,實(shí)現(xiàn)實(shí)時(shí)追蹤文件變更,達(dá)到類似shell命令tail -f的效果,感興趣的小伙伴可以了解一下
    2023-08-08
  • go?閉包c(diǎn)ase示例代碼

    go?閉包c(diǎn)ase示例代碼

    這篇文章解釋了Go語(yǔ)言中匿名函數(shù)、閉包、立即執(zhí)行函數(shù)表達(dá)式(IIFE)和變量作用域的概念,它通過一個(gè)示例代碼展示了匿名函數(shù)如何捕獲并修改外部變量,以及如何使用立即執(zhí)行函數(shù)表達(dá)式來立即執(zhí)行這個(gè)匿名函數(shù),感興趣的朋友一起看看吧
    2025-02-02
  • Go語(yǔ)言實(shí)現(xiàn)lru淘汰策略和超時(shí)過期

    Go語(yǔ)言實(shí)現(xiàn)lru淘汰策略和超時(shí)過期

    緩存的大小是有限的,當(dāng)添加數(shù)據(jù)發(fā)現(xiàn)剩余緩存不夠時(shí),需要淘汰緩存中的部分?jǐn)?shù)據(jù),本文主要介紹了Go語(yǔ)言實(shí)現(xiàn)lru淘汰策略和超時(shí)過期,感興趣的可以了解一下
    2024-02-02
  • Golang中interface的基本用法詳解

    Golang中interface的基本用法詳解

    Go 中接口也是一個(gè)使用得非常頻繁的特性,好的軟件設(shè)計(jì)往往離不開接口的使用,比如依賴倒置原則(通過抽象出接口,分離了具體實(shí)現(xiàn)與實(shí)際使用的耦合)。 今天,就讓我們來了解一下 Go 中接口的一些基本用法
    2023-01-01
  • GO中公平鎖和非公平鎖的具體使用

    GO中公平鎖和非公平鎖的具體使用

    公平鎖和非公平鎖是計(jì)算機(jī)科學(xué)中的兩種鎖機(jī)制,它們主要用于多線程編程,以控制對(duì)共享資源的訪問,本文主要介紹了GO中公平鎖和非公平鎖的具體使用,感興趣的可以了解一下
    2024-08-08
  • go語(yǔ)言搬磚之go jmespath實(shí)現(xiàn)查詢json數(shù)據(jù)

    go語(yǔ)言搬磚之go jmespath實(shí)現(xiàn)查詢json數(shù)據(jù)

    這篇文章主要為大家介紹了go語(yǔ)言搬磚之go jmespath實(shí)現(xiàn)查詢json數(shù)據(jù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • 深入解析golang編程中函數(shù)的用法

    深入解析golang編程中函數(shù)的用法

    這篇文章主要介紹了golang編程中函數(shù)的用法,是Go語(yǔ)言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-10-10
  • GO語(yǔ)言基本類型分析

    GO語(yǔ)言基本類型分析

    這篇文章主要介紹了GO語(yǔ)言基本類型,較為詳細(xì)的分析了整形、浮點(diǎn)型、字符串、指針等類型的具體用法,是深入學(xué)習(xí)GO語(yǔ)言所必須掌握的重要基礎(chǔ),需要的朋友可以參考下
    2014-12-12
  • 詳解golang的切片擴(kuò)容機(jī)制

    詳解golang的切片擴(kuò)容機(jī)制

    golang的切片擴(kuò)容機(jī)制是golang面試者繞不開的一扇大門,無(wú)論在面試提問,或者面試情景上都繞不開它,今天就說說我理解下的切片擴(kuò)容機(jī)制,感興趣的小伙伴跟著小編一起來看看吧
    2023-07-07

最新評(píng)論