日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

介绍一个对陌生程序快速进行性能瓶颈分析的技巧

發(fā)布時間:2023/12/18 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 介绍一个对陌生程序快速进行性能瓶颈分析的技巧 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  

前言

???????? 工作多年,一直做的是curd系統(tǒng)。前幾年做的系統(tǒng)應(yīng)用場景,大多對數(shù)據(jù)庫依賴比較重。例如報表統(tǒng)計,數(shù)據(jù)遷移,批量對賬等。所以這些系統(tǒng)出現(xiàn)性能瓶頸一般出在數(shù)據(jù)庫操作上面。

???????? 如果程序因?yàn)閿?shù)據(jù)庫操作出現(xiàn)性能瓶頸是比較好辦的,因?yàn)閛racle提供了完善的性能分析工具。往往使用awr報告簡單分析一下(top sql和top event)就可以獲知有哪些sql有異常。

???????? 找出問題sql,根據(jù)經(jīng)驗(yàn)進(jìn)行優(yōu)化即可,例如沒索引的加索引,有索引沒走的加hint,IO太慢的話加并行之類。之前我整理過的一些數(shù)據(jù)庫sql優(yōu)化經(jīng)驗(yàn)在博客里面發(fā)過。

?

?

?

?

?

?

? ? ? ???更多關(guān)于數(shù)據(jù)庫應(yīng)用優(yōu)化的知識見這里:https://www.cnblogs.com/kingstarer/p/9613626.html

?

? ? ? ? ?但今年做的系統(tǒng),有時也會出現(xiàn)數(shù)據(jù)庫資源充足,但由于程序自身寫得不好,導(dǎo)致cpu消耗太高,系統(tǒng)反應(yīng)緩慢的情況。

???????? 這種如果是自己寫的程序相對比較好處理,因?yàn)閷懙臅r候大概會知道哪些地方容易出問題。

???????? 但有時也會有接手別人的程序出現(xiàn)問題需要優(yōu)化的情況,這種以前我是都需要花時間重新看一下他們的源碼,然后結(jié)合日志分析問題出哪里,效率相對比較低。

???????? 不過最近我發(fā)現(xiàn)一個工具,能直觀地統(tǒng)計出程序資源消耗,對于優(yōu)化幫助特別大。今年我有幾次對項目組的程序做優(yōu)化,都是先用它發(fā)現(xiàn)問題關(guān)鍵,然后再進(jìn)行優(yōu)化的。

這種方式比以前憑經(jīng)驗(yàn)分析好,因?yàn)橛袝r自己覺得有問題的代碼,優(yōu)化后發(fā)現(xiàn)效果甚微。(代碼使用頻率低,或者瓶頸出現(xiàn)在其它地方。)例如今年我曾經(jīng)把系統(tǒng)取環(huán)境變量的代碼,從原來直接使用getenv,改為從緩存里面取數(shù)(getenv是順序查找,緩存取是自己寫的二分查找),但發(fā)現(xiàn)對于系統(tǒng)整體性能提高不到1%。

???????? 下面以一次項目組優(yōu)化的過程為例,給大家介紹一下這個工具----callgrind的用法:

?

概述

???????? callgrind是vallgrind工具家族中的一員,它相比其它性能測試工具的好處是不需要修改源碼、編譯選項(推薦加-g,但不是必要的)、系統(tǒng)參數(shù)等。但也存在缺點(diǎn),如分析過程中程序性能下降較大,無法對已啟動的進(jìn)程進(jìn)行性能分析,無法分析函數(shù)實(shí)際耗時(分析的是消耗cpu時間,如果存在sleep、wait之類函數(shù)會影響分析結(jié)果),對遞歸調(diào)用展示不友好等。不過好在我們項目中,這些缺點(diǎn)不太影響我們使用。

???????? callgrind分析完程序后會使用Ir(指令執(zhí)行的次數(shù))來統(tǒng)計程序中函數(shù)調(diào)用消耗,同時還會建立函數(shù)調(diào)用關(guān)系圖,需要分析程序流程時可以參考。同時callgrind還能分析程序緩存使用情況,幫助我們優(yōu)化if和switch順序。還有分析鎖順序等其它功能。

每次運(yùn)行結(jié)束時,它會把分析數(shù)據(jù)寫入一個文件,之后我們可以通過callgrind_annotate或kcachegrind讀取分析結(jié)果展示成可讀的報告。

???????? 接下來我介紹callgrind的使用心得。

背景

rcc查詢業(yè)務(wù)由于業(yè)務(wù)量增長,現(xiàn)在部署了查詢的三臺機(jī)器平時cpu負(fù)荷接近50%,在交易量偏大時cpu會增漲到100%。

項目組臨時投入新 機(jī)器資源將cpu消耗控制到25~50%,以減少系統(tǒng)性能告警。但后續(xù)仍需對應(yīng)用進(jìn)行優(yōu)化,以防故障再次發(fā)生。

問題還原與分析

在測試環(huán)境上經(jīng)過一番配置,還原了系統(tǒng)故障現(xiàn)象。仔細(xì)觀察可以發(fā)現(xiàn):

在并發(fā)數(shù)比較低時,系統(tǒng)cpu消耗較低,但并發(fā)數(shù)高一些時,系統(tǒng)cpu消耗急劇上漲,很快就到達(dá)100%,但此時tps基本不變。

并發(fā)數(shù)

cpu使用率

tps

6

約60%

73

12

約100%

68

觀察top和vmstat信息,發(fā)現(xiàn)兩個異常:

1 vmstat顯示user消耗超過90%,而sys只占不到10%。對于非計算密集應(yīng)用,這個比例有點(diǎn)高

?

2 top顯示系統(tǒng)消耗cpu最多的進(jìn)程并非業(yè)務(wù)服務(wù)進(jìn)程,而是加解密相關(guān)的服務(wù)進(jìn)程

?

圖示:QueryBridgeSrv和QuerySecSrv消耗了比較多的cpu資源。而Query核心業(yè)務(wù)進(jìn)程反而消耗得不是很多。(從下到上cpu消耗逐漸下降)

?

業(yè)務(wù)服務(wù)代碼經(jīng)常修改,項目組開發(fā)人員比較熟悉,通過日志即可迅速定位問題出在哪。但是報文較驗(yàn)轉(zhuǎn)換服務(wù)由于修改的比較少,比較難定位問題,所以決定使用callgrind輔助分析。

callgrind一般用法

對于一般的程序,我們可以直接啟動callgrind分析程序,只需要在命令行前面加上"valgrind --tool=callgrind ",如下:

?

?

等程序運(yùn)行完退出后會在目錄生成分析文件,命名為callgrind.out.進(jìn)程號文件,我們可以使用callgrind_annotate在命令行界面上對其進(jìn)行分析,但一般是拿到windows環(huán)境下使用kcachegrind分析。

?

?

callgrind在項目中的用法

由于項目中的程序是以服務(wù)形式啟動的,不會自然退出,所以需要使用另外的方法收集分析結(jié)果文件。

?

單進(jìn)程程序QueryBridgeSrv分析方法:

???????? 由于QueryBridgeSrv服務(wù)是單進(jìn)程程序,所以只需要直接啟動即可。

?

???????? 不過由于我們項目把很多程序啟動參數(shù)放在環(huán)境變量,不設(shè)置的話啟動會出異常。所以啟動前需要設(shè)置環(huán)境變量,可以使用以下腳本獲取QueryBridgeSrv程序環(huán)境變量

?

????????

???????? 執(zhí)行腳本后即可獲取設(shè)置環(huán)境變量語句,執(zhí)行后即可正常啟動

???????? time valgrind --tool=callgrind --callgrind-out-file="callgrind.bridge_1305_%p.out"? QueryBridgeSrv 1305 17 2001 2002 # callgrind-out-file選項是指定生成的分析文件名字 更多選項可參考man valgrind

????????

進(jìn)程啟動后我們就可以開始執(zhí)行正常的測試用例,讓callgrind分析程序運(yùn)行情況。等運(yùn)行得差不多了,我們可以在其它會話窗口執(zhí)行callgrind_control命令將收集的信息文件輸出。

callgrind_control選項也不少,一般我們會使用到以下兩個選項:

?

callgrind_control -d # dump出目前收集的信息

callgrind_control -k # 停止callgrind(不會輸出收集文件 所以先要dump)

?

?

多進(jìn)程程序QuerySecSrv分析方法:

???????? 對于多進(jìn)程程序,最好由項目的Daemon進(jìn)程啟動。所以我們可以設(shè)計一個啟動腳本放到bin目錄下面:

????????

???????? 然后修改tbl_srv_param參數(shù),將啟動程序名字由QuerySecSrv改為QuerySecSrv.sh

???????? 這樣Daemon就會啟動QuerySecSrv.sh,然后由QuerySecSrv.sh啟動callgrind對QuerySecSrv進(jìn)行分析。

???????? 進(jìn)程啟動后獲取分析結(jié)果文件方法與QueryBridgeSrv一致。

kcachegrind介紹

???????? 對于生成的文件,我們可以使用kcachegrind進(jìn)行分析:使用kcachegrind打開之前我們分析QueryBridgeSrv的結(jié)果文件(文件一定要以"callgrind."開頭),顯示如下:

?

???????? 左上角的Flat Profile窗格,第一列是函數(shù)消耗的總資源(包括函數(shù)本身開銷和函數(shù)內(nèi)部調(diào)用的子函數(shù)開銷之和),第二列是函數(shù)本身的開銷。

???????? 可以想象,main函數(shù)一般是系統(tǒng)中總開銷最大的,因?yàn)榇蟛糠趾瘮?shù)是由main函數(shù)調(diào)用的。但是main函數(shù)自身消耗可能不多,大部分指令是它調(diào)用的其它函數(shù)消耗的。

???????? 右上角的窗格(后面稱callers窗格),我們一般用來顯示該函數(shù)被調(diào)用的信息(callers),如圖,可以看出GenCtx函數(shù)只有一個調(diào)用者GenSecHead。

???????? 右下角窗口(后面稱callees窗格),我們一般用來顯示該函數(shù)調(diào)用其它函數(shù)信息(callees),如圖,可以看出GenCtx函數(shù)調(diào)用了好多個函數(shù)及分別消耗的指令數(shù)。

???????? 因?yàn)槲覀円话悴魂P(guān)心函數(shù)實(shí)際開銷,而是關(guān)心函數(shù)相對開銷,所以kcachegrind提供了兩個按鈕,把開銷顯示成百分比。

???????? (百分號控制的是Flat Profile窗口顯示方式,十字箭頭控制的是Callers和Callees窗格)

???

???????? 按百分比顯示后我們可以清楚地看出memset函數(shù)占用了程序開銷的73%,而且消耗在其自身。(Self)

?  

???????? 對于一般應(yīng)用,memset函數(shù)是沒有優(yōu)化空間的,所以我們要觀察是哪些函數(shù)調(diào)用了memset這么多次。

???????? 在Flat Profile窗口單擊memset函數(shù),可以看到調(diào)用memset函數(shù)的信息

?  

???????? 從上圖我們可以看出20%的memset調(diào)用消耗是由于GenCtx引起的,我們先看看這個函數(shù)。在Callers窗格雙擊,可以進(jìn)到GenCtx函數(shù)的分析(分析過程可以使用工具欄的導(dǎo)航按鈕前后跳轉(zhuǎn))

????????

???????? 可以看到GenCtx函數(shù)50%的消耗在于memset,我們可以到對應(yīng)函數(shù)看有沒有調(diào)用必要。

???????? 在Flat Profile窗格下拉列表選擇source file就可以看到函數(shù)所在源文件。由于windows環(huán)境下代碼路徑問題,無法在kcachegrind直接查看代碼信息,只能另外打開vs查看代碼。(根據(jù)網(wǎng)上介紹,使用callgrind_annotate可以直接看到每行代碼消耗指令數(shù),對于分析長函數(shù)幫助很大,暫時未在項目中實(shí)踐)

?

在源碼里面我們發(fā)現(xiàn)幾處memset調(diào)用,作用是把某大塊內(nèi)存(395k)初始化為零。經(jīng)分析,這幾處地方并不是特別需要調(diào)用memset。應(yīng)是當(dāng)時寫代碼時使用防御性編程技巧,寧殺錯,不放過,統(tǒng)一清零。當(dāng)這個函數(shù)只調(diào)用一次時,這些操作對系統(tǒng)性能消耗不算多。但當(dāng)業(yè)務(wù)量比較大,函數(shù)調(diào)用次數(shù)較多時,這種初始化操作會給系統(tǒng)帶來較大性能消耗。

把初始化代碼代碼注釋了(如下),重新編譯程序,驗(yàn)證發(fā)現(xiàn)功能不受影響。

????????

這里本來應(yīng)該要貼問題代碼,但這里是博客,就不貼了,避免泄密風(fēng)險。

//注意,這里變量初始化為零,其實(shí)也可能導(dǎo)致隱式調(diào)用了memset(具體看編譯器實(shí)現(xiàn))

?

???????? 繼續(xù)使用kcachegrind分析其它函數(shù),把不必要的memset都改掉,再重新跑。發(fā)現(xiàn)memset消耗降低了很多。

????????

???????? 用同樣方法對QuerySecSrv進(jìn)行分析,發(fā)現(xiàn)也主要是memset消耗占大頭,一樣修改。

kcachegrind輸出函數(shù)調(diào)用關(guān)系圖

使用kcachegrind還可以輸出函數(shù)調(diào)用關(guān)系及消耗信息全局視圖進(jìn)行分析:

單擊main(或者其它想要分析的函數(shù)),在callees窗格切換到Call Graph選項,在出現(xiàn)的程序調(diào)用圖右鍵可以設(shè)置圖例選項。(一般建議修改Min.Node Cost選項,把5%改成1%,默認(rèn)不顯示調(diào)用消耗低于5%的函數(shù))

?

在kcachegrind看大圖片不方便,我們可以使用Export Graph功能導(dǎo)出圖片,放到看圖工具里面查看。

?

?

?

這個功能對于學(xué)習(xí)程序邏輯也很有幫助。

成果

???????? 修改驗(yàn)證通過后后,對系統(tǒng)重新進(jìn)行非功能測試,結(jié)果如下:

并發(fā)數(shù)

cpu使用率

tps

9

約60%

252

30

約100%

335

?

?

???????? 圖示:cpu使用率100%時us/sy有所下降

?

?

圖示:優(yōu)化后報文較驗(yàn)轉(zhuǎn)換服務(wù)已退出cpu占用top10(從下到上cpu消耗逐漸下降)

結(jié)語

???????? 使用callgrind可以幫助我們快速定位系統(tǒng)性能瓶頸,根據(jù)callgrind分析結(jié)果針對性對程序進(jìn)行優(yōu)化,分析過程也可以輸出流程圖輔助我們理解程序和單元測試,推薦大家了解一下。

轉(zhuǎn)載于:https://www.cnblogs.com/kingstarer/p/10202857.html

總結(jié)

以上是生活随笔為你收集整理的介绍一个对陌生程序快速进行性能瓶颈分析的技巧的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。