初識火焰圖


http://yangxikun.github.io/linux%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90/2016/09/24/flame-graph.html

火焰圖的分類


壓測程序時,火焰圖能夠幫助我們直觀地瞭解到程序的性能瓶頸。本文主要是記錄下在生成火焰圖的時候的一些注意事項。以下鏈接是對每個類別的火焰圖的詳細說明。

  1. On-CPU:CPU Flame Graphs
  2. Off-CPU:Off-CPU Flame Graphs
  3. Memory:Memory Leak (and Growth) Flame Graphs
  4. Hot/Cold:Hot/Cold Flame Graphs
  5. Differential:Differential Flame Graphs

關於火焰圖的PPT(講解得非常詳細):Blazing Performance with Flame Graphs

如何生成火焰圖


首先是需要在程序運行時,對其進行採樣。linux下常用的有perf和systemtap,我這裏用了systemtap來做實驗,因爲已經牛人寫好了一些systemtap相應的腳本可以直接拿來用了:nginx-systemtap-toolkit

systemtap依賴的安裝:

1、CentOS

shell> yum install yum-utils
shell> yum install kernel-devel
shell> debuginfo-install kernel
shell> yum install systemtap

在執行debuginfo-install kernel的時候,沒能安裝成功,於是就直接到http://debuginfo.centos.org/7下載相應的包手動安裝了。

2、Debian

shell> apt-get install systemtap linux-image-`uname -r`-dbg linux-headers-`uname -r`

systemtap的工作原理:

systemtap腳本——>翻譯爲C程序——>編譯爲內核模塊——>安裝到內核上運行,開始採樣——>結束採樣,從內核卸載

我用nginx-systemtap-toolkit提供的兩個perl腳本(它們會根據參數生成相應的systemtap腳本並執行)做了實驗:

  • sample-bt:用來生成 On-CPU 火焰圖的採樣數據
  • sample-bt-off-cpu:用來生成 Off-CPU 火焰圖的採樣數據

注意事項:

1、普通用戶身份無法執行systemtap。

2、什麼時候開始採樣?

當執行sample-bt -p 50417 -t 5 -u > sample.bt的時候,需要等到輸出類似Tracing pid (exec_path) in kernel|user -space...的時候才真正開始採樣。可以爲sample-bt加多一個參數-a '-vv'就可以看到一些debug輸出。

3、理解On-CPU採樣的工作原理

原理是定時地判斷當前cpu上運行的進程是否爲要採樣的進程,如果是的話就根據設置的採樣點進行採樣。

如果被採樣的進程一直處於就緒狀態,沒有被調度執行,那麼你將會看到sample-bt的輸出如下面這樣:

爲何沒有停止呢?這就需要從sample-bt生成的systemtap腳本看看有沒什麼線索了:

執行sample-bt -p 114356 -t 5 -u -a '-vv' -d ,這裏多加了一個-d參數,讓sample-bt輸出生成的systemtap腳本:

/*
target()是systemtap的函數庫Tapset提供的,用於獲取當前採樣的進程pid
*/
probe begin {
    warn(sprintf("Tracing %d (/usr/sbin/mysqld) in user-space only...\n", target()))
}


global bts;
global quit = 0;

probe timer.profile {//每個一段時間被調用一次
    if (pid() == target()) {//當前運行的進程與被採樣的進程是否爲同一個
        if (!quit) {
            bts[ubacktrace()] <<< 1;

        } else {
            //採樣停止
            foreach (bt in bts- limit 1024) {
                print_ustack(bt);
                printf("\t%d\n", @count(bts[bt]));
            }

            exit()
        }
    }
}

probe timer.s(5) {//5秒後執行
    nstacks = 0
    foreach (bt in bts limit 1) {
        nstacks++
    }

    if (nstacks == 0) {//沒采樣到數據直接退出
        warn("No backtraces found. Quitting now...\n")
        exit()

    } else {//採樣到數據了,設置停止標誌
        warn("Time's up. Quitting now...(it may take a while)\n")
        quit = 1
    }
}

所以上圖中重複的輸出了Time's up. Quitting now...(it may take a while)是因爲開始採樣後,timer.profile採樣到數據,timer.s設置了停止標誌之後,在timer.profile執行時一直沒遇到被採樣的進程被調度執行。此時只需要讓這個進程被調度執行就行了,比如:如果該進程是一個服務,可以發送個請求給它。

對於Off-CPU採樣的工作原理,同樣可以使用sample-bt-off-cpu -a '-vv' -u -p 114356 -t 5 -d查看生成的systemtap腳本。

生成火焰圖的步驟:

  1. 採樣:sample-bt -p 92869 -t 10 -u -a '-vv' > a.bt
  2. 轉化爲火焰圖:stackcollapse-stap.pl a.bt > a.cbt;flamegraph.pl a.cbt > a.svg

測試時生成的一個On-CPU的圖片,從圖中可看出頻繁的tcp connect和close是目前的瓶頸之一: 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章