亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

一、perf簡(jiǎn)介

從2.6.31內(nèi)核開(kāi)始,linux內(nèi)核自帶了一個(gè)性能分析工具perf,能夠進(jìn)行函數(shù)級(jí)與指令級(jí)的熱點(diǎn)查找。通過(guò)它,應(yīng)用程序可以利用 PMU,tracepoint 和內(nèi)核中的特殊計(jì)數(shù)器來(lái)進(jìn)行性能統(tǒng)計(jì)。它不但可以分析指定應(yīng)用程序的性能問(wèn)題 (per thread),也可以用來(lái)分析內(nèi)核的性能問(wèn)題,當(dāng)然也可以同時(shí)分析應(yīng)用代碼和內(nèi)核,從而全面理解應(yīng)用程序中的性能瓶頸。

Perf是內(nèi)置于Linux內(nèi)核源碼樹(shù)中的性能剖析(profiling)工具。它基于事件采樣原理,以性能事件為基礎(chǔ),支持針對(duì)處理器相關(guān)性能指標(biāo)與操作系統(tǒng)相關(guān)性能指標(biāo)的性能剖析,常用于性能瓶頸的查找與熱點(diǎn)代碼的定位。

1.1安裝Perf

安裝 perf 非常簡(jiǎn)單, 只要內(nèi)核版本高于2.6.31的, perf已經(jīng)被內(nèi)核支持. 首先安裝內(nèi)核源碼:

apt-get install linux-source

那么在 /usr/src 目錄下就已經(jīng)下載好了內(nèi)核源碼, 我們對(duì)源碼包進(jìn)行解壓, 然后進(jìn)入 tools/perf 目錄然后敲入下面兩個(gè)命令即可:

make
make install

可能因?yàn)橄到y(tǒng)原因, 需要提前安裝下面的開(kāi)發(fā)包:

apt-get install -y binutils-dev
apt-get install -y libdw-dev
apt-get install -y Python/ target=_blank class=infotextkey>Python-dev
apt-get install -y libnewt-dev

1.2Perf的基本使用

CPU周期(cpu-cycles)是默認(rèn)的性能事件,所謂的CPU周期是指CPU所能識(shí)別的最小時(shí)間單元,通常為億分之幾秒,是CPU執(zhí)行最簡(jiǎn)單的指令時(shí)所需要的時(shí)間,例如讀取寄存器中的內(nèi)容,也叫做clock tick。

perf COMMAND [-e event ...] PROGRAM, perf 是采用的這么一個(gè)命令格式, COMMAND一般常用的就是 top, stat, record, report等. 然后用 -e 參數(shù)來(lái)統(tǒng)計(jì)需要關(guān)注的事件. 多個(gè)事件就用多個(gè) -e 連接。

Perf是一個(gè)包含22種子工具的工具集,以下是最常用的5種:

  • perf-list
  • perf-stat
  • perf-top
  • perf-record
  • perf-report
  • perf-trace

perf-list

Perf-list用來(lái)查看perf所支持的性能事件,有軟件的也有硬件的。
List all symbolic event types。

perf list [hw | sw | cache | tracepoint | event_glob]

perf stat

說(shuō)明一個(gè)工具的最佳途徑是列舉一個(gè)例子。考查下面這個(gè)例子程序。其中函數(shù) longa() 是個(gè)很長(zhǎng)的循環(huán),比較浪費(fèi)時(shí)間。函數(shù) foo1 和 foo2 將分別調(diào)用該函數(shù) 10 次,以及 100 次。

//t1.c
 void longa()
 {
   int i,j;
   for(i = 0; i < 1000000; i++)
   j=i; //am I silly or crazy? I feel boring and desperate.
 }

 void foo2()
 {
   int i;
   for(i=0 ; i < 10; i++)
        longa();
 }

 void foo1()
 {
   int i;
   for(i = 0; i< 100; i++)
      longa();
 }

 int mAIn(void)
 {
   foo1();
   foo2();
 }

然后編譯它:

gcc -o t1 -g t1.c

下面演示了 perf stat 針對(duì)程序 t1 的輸出:

root@ubuntu-test:~# perf stat ./t1

 Performance counter stats for './t1':

        218.584169 task-clock # 0.997 CPUs utilized
                18 context-switches # 0.000 M/sec
                 0 CPU-migrations # 0.000 M/sec
                82 page-faults # 0.000 M/sec
       771,180,100 cycles # 3.528 GHz
     <not counted> stalled-cycles-frontend
     <not counted> stalled-cycles-backend
       550,703,114 instructions # 0.71 insns per cycle
       110,117,522 branches # 503.776 M/sec
             5,009 branch-misses # 0.00% of all branches

       0.219155248 seconds time elapsed

程序 t1 是一個(gè) CPU bound 型,因?yàn)?task-clock-msecs 接近 1

對(duì) t1 進(jìn)行調(diào)優(yōu)應(yīng)該要找到熱點(diǎn) ( 即最耗時(shí)的代碼片段 ),再看看是否能夠提高熱點(diǎn)代碼的效率。缺省情況下,除了 task-clock-msecs 之外,perf stat 還給出了其他幾個(gè)最常用的統(tǒng)計(jì)信息:

  • Task-clock-msecs:CPU 利用率,該值高,說(shuō)明程序的多數(shù)時(shí)間花費(fèi)在 CPU 計(jì)算上而非 IO。
  • Context-switches:進(jìn)程切換次數(shù),記錄了程序運(yùn)行過(guò)程中發(fā)生了多少次進(jìn)程切換,頻繁的進(jìn)程切換是應(yīng)該避免的。
  • Cache-misses:程序運(yùn)行過(guò)程中總體的 cache 利用情況,如果該值過(guò)高,說(shuō)明程序的 cache 利用不好
  • CPU-migrations:表示進(jìn)程 t1 運(yùn)行過(guò)程中發(fā)生了多少次 CPU 遷移,即被調(diào)度器從一個(gè) CPU 轉(zhuǎn)移到另外一個(gè) CPU 上運(yùn)行。
  • Cycles:處理器時(shí)鐘,一條機(jī)器指令可能需要多個(gè) cycles,Instructions: 機(jī)器指令數(shù)目。
  • IPC:是 Instructions/Cycles 的比值,該值越大越好,說(shuō)明程序充分利用了處理器的特性。
  • Cache-references: cache 命中的次數(shù),Cache-misses: cache 失效的次數(shù)。

通過(guò)指定 -e 選項(xiàng),您可以改變 perf stat 的缺省事件 ( 關(guān)于事件,在上一小節(jié)已經(jīng)說(shuō)明,可以通過(guò) perf list 來(lái)查看 )。假如您已經(jīng)有很多的調(diào)優(yōu)經(jīng)驗(yàn),可能會(huì)使用 -e 選項(xiàng)來(lái)查看您所感興趣的特殊的事件。

有些程序慢是因?yàn)橛?jì)算量太大,其多數(shù)時(shí)間都應(yīng)該在使用 CPU 進(jìn)行計(jì)算,這叫做 CPU bound 型;有些程序慢是因?yàn)檫^(guò)多的 IO,這種時(shí)候其 CPU 利用率應(yīng)該不高,這叫做 IO bound 型;對(duì)于 CPU bound 程序的調(diào)優(yōu)和 IO bound 的調(diào)優(yōu)是不同的。

perf top

使用 perf stat 的時(shí)候,往往您已經(jīng)有一個(gè)調(diào)優(yōu)的目標(biāo)。比如我剛才寫(xiě)的那個(gè)無(wú)聊程序 t1。

也有些時(shí)候,您只是發(fā)現(xiàn)系統(tǒng)性能無(wú)端下降,并不清楚究竟哪個(gè)進(jìn)程成為了貪吃的 hog。

此時(shí)需要一個(gè)類(lèi)似 top 的命令,列出所有值得懷疑的進(jìn)程,從中找到需要進(jìn)一步審查的家伙。

Perf top 用于實(shí)時(shí)顯示當(dāng)前系統(tǒng)的性能統(tǒng)計(jì)信息。該命令主要用來(lái)觀察整個(gè)系統(tǒng)當(dāng)前的狀態(tài),比如可以通過(guò)查看該命令的輸出來(lái)查看當(dāng)前系統(tǒng)最耗時(shí)的內(nèi)核函數(shù)或某個(gè)用戶(hù)進(jìn)程。

讓我們?cè)僭O(shè)計(jì)一個(gè)例子來(lái)演示吧,我很快就想到了如代碼清單 2 所示的一個(gè)程序:

//t2.c
main(){
    int i;
    while(1) i++;
}

然后編譯這個(gè)程序:

gcc -o t2 -g t2.c

運(yùn)行這個(gè)程序后, 我們另起一個(gè)窗口,運(yùn)行perf top來(lái)看看:

Events: 8K cycles
 98.67% t2 [.] main
  1.10% [kernel] [k] __do_softirq
  0.07% [kernel] [k] _raw_spin_unlock_irqrestore
  0.05% perf [.] kallsyms__parse
  0.05% libc-2.15.so [.] 0x807c7
  0.05% [kernel] [k] kallsyms_expand_symbol
  0.02% perf [.] map__process_kallsym_symbol

很容易便發(fā)現(xiàn) t2 是需要關(guān)注的可疑程序。不過(guò)其作案手法太簡(jiǎn)單:肆無(wú)忌憚地浪費(fèi)著 CPU。所以我們不用再做什么其他的事情便可以找到問(wèn)題所在。但現(xiàn)實(shí)生活中,影響性能的程序一般都不會(huì)如此愚蠢,所以我們往往還需要使用其他的 perf 工具進(jìn)一步分析。

使用 perf record, 解讀 report

使用 top 和 stat 之后,您可能已經(jīng)大致有數(shù)了。要進(jìn)一步分析,便需要一些粒度更細(xì)的信息。比如說(shuō)您已經(jīng)斷定目標(biāo)程序計(jì)算量較大,也許是因?yàn)橛行┐a寫(xiě)的不夠精簡(jiǎn)。那么面對(duì)長(zhǎng)長(zhǎng)的代碼文件,究竟哪幾行代碼需要進(jìn)一步修改呢?這便需要使用 perf record 記錄單個(gè)函數(shù)級(jí)別的統(tǒng)計(jì)信息,并使用 perf report 來(lái)顯示統(tǒng)計(jì)結(jié)果。

您的調(diào)優(yōu)應(yīng)該將注意力集中到百分比高的熱點(diǎn)代碼片段上,假如一段代碼只占用整個(gè)程序運(yùn)行時(shí)間的 0.1%,即使您將其優(yōu)化到僅剩一條機(jī)器指令,恐怕也只能將整體的程序性能提高 0.1%。俗話說(shuō),好鋼用在刀刃上,不必我多說(shuō)了。

perf record -e cpu-clock ./t1
perf report

perf report 輸出結(jié)果:

Events: 229 cpu-clock
100.00% t1 t1 [.] longa

不出所料,hot spot 是 longa( ) 函數(shù)。但,代碼是非常復(fù)雜難說(shuō)的,t1 程序中的 foo1() 也是一個(gè)潛在的調(diào)優(yōu)對(duì)象,為什么要調(diào)用 100 次那個(gè)無(wú)聊的 longa() 函數(shù)呢?但我們?cè)谏蠄D中無(wú)法發(fā)現(xiàn) foo1 和 foo2,更無(wú)法了解他們的區(qū)別了。

我曾發(fā)現(xiàn)自己寫(xiě)的一個(gè)程序居然有近一半的時(shí)間花費(fèi)在 string 類(lèi)的幾個(gè)方法上,string 是 C++ 標(biāo)準(zhǔn),我絕不可能寫(xiě)出比 STL 更好的代碼了。因此我只有找到自己程序中過(guò)多使用 string 的地方。因此我很需要按照調(diào)用關(guān)系進(jìn)行顯示的統(tǒng)計(jì)信息。

使用 perf 的 -g 選項(xiàng)便可以得到需要的信息:

perf record -e cpu-clock -g ./t1
perf report

輸出結(jié)果:

Events: 270 cpu-clock
- 100.00% t1 t1 [.] longa
   - longa
      + 91.85% foo1
      + 8.15% foo2

通過(guò)對(duì) calling graph 的分析,能很方便地看到 91.85% 的時(shí)間都花費(fèi)在 foo1() 函數(shù)中,因?yàn)樗{(diào)用了 100 次 longa() 函數(shù),因此假如 longa() 是個(gè)無(wú)法優(yōu)化的函數(shù),那么程序員就應(yīng)該考慮優(yōu)化 foo1,減少對(duì) longa() 的調(diào)用次數(shù)。

使用 tracepoint

當(dāng) perf 根據(jù) tick 時(shí)間點(diǎn)進(jìn)行采樣后,人們便能夠得到內(nèi)核代碼中的 hot spot。那什么時(shí)候需要使用 tracepoint 來(lái)采樣呢?

我想人們使用 tracepoint 的基本需求是對(duì)內(nèi)核的運(yùn)行時(shí)行為的關(guān)心,如前所述,有些內(nèi)核開(kāi)發(fā)人員需要專(zhuān)注于特定的子系統(tǒng),比如內(nèi)存管理模塊。這便需要統(tǒng)計(jì)相關(guān)內(nèi)核函數(shù)的運(yùn)行情況。另外,內(nèi)核行為對(duì)應(yīng)用程序性能的影響也是不容忽視的:

以之前的遺憾為例,假如時(shí)光倒流,我想我要做的是統(tǒng)計(jì)該應(yīng)用程序運(yùn)行期間究竟發(fā)生了多少次系統(tǒng)調(diào)用。在哪里發(fā)生的?

下面我用 ls 命令來(lái)演示 sys_enter 這個(gè) tracepoint 的使用:

root@ubuntu-test:~# perf stat -e raw_syscalls:sys_enter ls
bin libexec off perf.data.old t1 t3 tutong.iso
bwtest minicom.log perf.data pktgen t1.c t3.c

 Performance counter stats for 'ls':

               111 raw_syscalls:sys_enter

       0.001557549 seconds time elapsed

個(gè)報(bào)告詳細(xì)說(shuō)明了在 ls 運(yùn)行期間發(fā)生了多少次系統(tǒng)調(diào)用 ( 上例中有 111 次 )。

二、常見(jiàn)性能問(wèn)題分析

性能測(cè)試大致分以下幾個(gè)步驟:

  1. 需求分析
  2. 腳本準(zhǔn)備
  3. 測(cè)試執(zhí)行
  4. 結(jié)果整理
  5. 問(wèn)題分析

需求描述:有一個(gè)服務(wù),啟動(dòng)時(shí)會(huì)加載一個(gè)1G的詞表文件到內(nèi)存,請(qǐng)求來(lái)了之后,會(huì)把請(qǐng)求詞去詞表里做模糊匹配,如果匹配到了就向一個(gè)后端服務(wù)發(fā)送一條http請(qǐng)求,拿回?cái)?shù)據(jù)之后,返回給客戶(hù)端的同時(shí),向MySQL記錄請(qǐng)求的唯一標(biāo)識(shí)和一個(gè)請(qǐng)求次數(shù)的標(biāo)記;

其中有幾個(gè)關(guān)鍵函數(shù)

模糊匹配(fuzzyMatching)

后端請(qǐng)求函數(shù)(sendingRequest)

拼裝請(qǐng)求函數(shù)(buildResponse)

記錄mysql請(qǐng)求次數(shù)標(biāo)記(signNum)

問(wèn)題及分析:

第一組:完全隨機(jī)請(qǐng)求詞,qps達(dá)到1k時(shí),服務(wù)器未見(jiàn)異常,cpu、內(nèi)存、帶寬均未滿,qps無(wú)法繼續(xù)提升;

  • 分析:由于此服務(wù)后端連接了其它服務(wù),所以在壓測(cè)之前,要確認(rèn)后端服務(wù)不會(huì)成為瓶頸點(diǎn),目前的狀態(tài)很可能是后端服務(wù)限制了被測(cè)服務(wù)的性能;此時(shí)可以檢查后端服務(wù)所在機(jī)器的各項(xiàng)指標(biāo),或者查看本機(jī)的連接狀況,一般后端服務(wù)無(wú)法處理,而被測(cè)服務(wù)又會(huì)一直向后面請(qǐng)求的話,timewait狀態(tài)的連接會(huì)變得比較多;

第二組:解決后端服務(wù)的問(wèn)題后,第二組使用平均30個(gè)字的請(qǐng)求詞,來(lái)打壓,qps到400時(shí),cpu load已滿;

  • 分析:這種情況明顯是由于fuzzyMatching函數(shù)計(jì)算效率的問(wèn)題導(dǎo)致cpu滿載,從而無(wú)法提升qps,使響應(yīng)時(shí)間不斷增大,此時(shí)可以通過(guò)perf+火焰圖來(lái)確定整個(gè)處理請(qǐng)求過(guò)程中響應(yīng)時(shí)間長(zhǎng)的函數(shù);此時(shí)需要評(píng)估壓測(cè)數(shù)據(jù)是否合理,如果線上平均請(qǐng)求詞只有2個(gè)的時(shí)候,此組測(cè)試明顯不合理,此時(shí)要開(kāi)發(fā)進(jìn)行性能優(yōu)化就是浪費(fèi)時(shí)間的;如果評(píng)估測(cè)試數(shù)據(jù)合理,可以再次更換短詞數(shù)據(jù)進(jìn)行壓測(cè)驗(yàn)證猜測(cè);

第三組:解決了上述兩個(gè)問(wèn)題之后,使用完全隨機(jī)請(qǐng)求詞,qps到達(dá)3k后降低至1k,然后再次提升到3k,如此反復(fù);

  • 分析:此時(shí)關(guān)注一下各項(xiàng)指標(biāo),排除了以上的問(wèn)題的話,操作mysql慢的問(wèn)題可能性大一些,對(duì)這種需要高并發(fā)的系統(tǒng)來(lái)說(shuō),直接讀寫(xiě)mysql不是個(gè)聰明的解決方案,一般會(huì)用redis做一層緩存,這里說(shuō)道的另一個(gè)問(wèn)題就是開(kāi)發(fā)設(shè)計(jì)不合理,導(dǎo)致的性能問(wèn)題;

第四組:將后端換做真實(shí)的服務(wù)來(lái)做整體壓測(cè),發(fā)現(xiàn)qps最高只能到300,此時(shí)檢查各項(xiàng)指標(biāo),發(fā)現(xiàn)入口帶寬占滿了;

  • 分析:這次問(wèn)題比較明顯,后端服務(wù)返回內(nèi)容過(guò)大,導(dǎo)致帶寬被占滿,此時(shí)依然需要評(píng)估需求:1、是否需要后端返回的所有數(shù)據(jù)內(nèi)容;2、評(píng)估更換萬(wàn)兆網(wǎng)卡的性?xún)r(jià)比;3、是否可以通過(guò)技術(shù)手段優(yōu)化帶寬占用,比如把一次請(qǐng)求分散到多組服務(wù)的多個(gè)請(qǐng)求;

 

2.1perf+火焰圖定位函數(shù)問(wèn)題

這里簡(jiǎn)單說(shuō)一下如何使用perf+火焰圖來(lái)直觀的定位性能問(wèn)題:

 

perf

Perf 擁有了眾多的性能分析能力,舉例來(lái)說(shuō),使用 Perf 可以計(jì)算每個(gè)時(shí)鐘周期內(nèi)的指令數(shù),稱(chēng)為 IPC,IPC 偏低表明代碼沒(méi)有很好地利用 CPU。Perf 還可以對(duì)程序進(jìn)行函數(shù)級(jí)別的采樣,從而了解程序的性能瓶頸究竟在哪里等等。Perf 還可以替代 strace,可以添加動(dòng)態(tài)內(nèi)核 probe 點(diǎn),還可以做 benchmark 衡量調(diào)度器的好壞。

  • 使用舉例:perf record -e cpu-clock -g -p 11110 -o data/perf.data sleep 30
  • -g 選項(xiàng)是告訴perf record額外記錄函數(shù)的調(diào)用關(guān)系 -e cpu-clock 指perf record監(jiān)控的指標(biāo)為cpu周期 -p 指定需要record的進(jìn)程pid

生成火焰圖

1、第一步:使用壓力測(cè)試工具對(duì)程序進(jìn)行打壓,壓到程序拐點(diǎn);

$sudo perf record -e cpu-clock -g -p 11110
Ctrl+c結(jié)束執(zhí)行后,在當(dāng)前目錄下會(huì)生成采樣數(shù)據(jù)perf.data.

2、第二步:用perf 工具對(duì)perf.data進(jìn)行解析

perf -i perf.data &> perf.unfold

3、第三步:將perf.unfold中的符號(hào)進(jìn)行折疊:

./stackcollapse-perf.pl perf.unfold &> perf.folded

4、最后生成svg圖:

./flamegraph.pl perf.folded > perf.svg

到這兒可以生成函數(shù)調(diào)用火焰圖,如下圖:

 

原生的perf可以直接定位C/C++的程序,通常編譯debug版本的程序能看到更多的信息,JAVA、go等語(yǔ)言可以通過(guò)各自定制的工具來(lái)生成,原理類(lèi)似;通過(guò)火焰圖可以輕松定位到哪個(gè)函數(shù)的處理時(shí)間最長(zhǎng),從而找到問(wèn)題所在。

分享到:
標(biāo)簽:perf
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定