程序調試和性能分析經常使用技巧

程序調試和性能分析經常使用技巧linux


程序調試和性能分析一般須要設計到多種工具,有時甚至須要跨越用戶態和內核態。本文總結了在程序調試和性能分析過程當中常碰到三個問題,既是爲了方便本身後面溫習,也是爲了和碰到一樣問題的朋友一塊兒分享。ubuntu


1.如何調試多線程的程序?數組


多線程程序運行的時候若是出現崩潰或者產生core的時候,最困難的是很難定位究竟是哪一個線程致使的問題。爲此,能夠利用gdb工具中的thread apply命令來指定在某個ID的線程上運行gdb命令,好比下面的命令就是在fuse進程的1至250號線程上運行bt命令,而後把全部線程的」bt」輸出統必定位到fuse.bt文件當中去。參考下面的命令能夠獲得全部線程的用戶態的堆棧多線程

gdb -q --batch -ex "thread apply 1-250 bt" attach `pidof fuse` | tee /home/qsia/fuse.btapp



2.如何在程序運行的過程當中修改某個變量的值?socket

gdb的attach命令可以和正在運行的進程相關聯,而''--ex」可以指按期望運行的gdb命令,再加上 表示屏蔽版本等信息的-q和表示批處理—batch的參數,就組成了能在程序運行時修改變量的參數組合。好比下面的命令,就在sksmon進程運行時,動態地修改了它的mask的值:tcp

 sudo    gdb -q --batch --ex "set msk=0" attach `pidofsksmon` ide


若是這個命令和上面的thread apply命令相結合,咱們就能寫出模擬多線程運行多種中間狀態的腳本,這樣可以極大的方便調試。函數



3.如何查看多線程程序的全部內核堆棧?工具


有時,咱們須要查看多線程的程序的全部內核態堆棧,這時咱們就須要充分利用Linux系統/proc文件系統的特性,進入到/proc下對應進程相關線程的目錄,讀出各自的」stack」信息。


cd /proc/`pidof yourprgoram_name`;

for i in `find ./ -name "stack"`; do echo $i >> ~/proc_search.log; cat $i >> ~/proc_search.log; done



4.如何分析程序關鍵函數的性能?

分析程序性能的工具不少,包括opprofile/systemtap等。Opprofile可以從CPU芯片和內核級別,給出系統的性能統計和分析,包括耗費CPU週期、Cache命中率等;而systemtap相似於SUN引入的DTrace,可以經過符號表生成可自動加載的探測驅動,從而可以統計系統運行時間、在指定函數插入特定函數。

針對特定業務應用的開發,通常而言,systemtap足夠勝任。


4.1 systemtap的安裝 


For Fedora/Centos/Redhat:

yum install systemtap

yum install kernel-devel gcc make

Prepare kernel debug information:

yum install yum-utils

debuginfo-install kernel



For ubuntu,Do it all with apt-get:

apt-get install systemtap

apt-get install linux-headers-generic gcc make

Prepare kernel debug information:

apt-get install linux-p_w_picpath-debug-generic

ln -s /boot/vmlinux-debug-$(uname -r) \

/lib/modules/$(uname -r)/vmlinux



4.2檢查sysstemtap是否安裝成功

運行命令 stap -v -e 'probe vfs.read {printf("read performed\n"); exit()}'

若是輸出正常就沒有問題,不然安裝還有問題。



4.3如何編寫stap監控腳本

和DTrace相似,systemtap運行的時候也須要stap腳本,請參考http://sourceware.org/systemtap/, 裏面有很是完整的介紹。示例代碼以下:

# Show sockets setting options# Return enabled or disabled based on value of optvalfunction getstatus(optval){    if ( optval == 1 )        return "enabling"    else        return "disabling"}probe begin{        print ("\nChecking for apps setting socket options\n")}# Set a socket optionprobe tcp.setsockopt{    status = getstatus(user_int($optval))        printf ("  App '%s' (PID %d) is %s socket option %s... ", execname(), pid(), status, optstr)}# Check setting the socket option workedprobe tcp.setsockopt.return{    if ( ret == 0 )        printf ("success")    else        printf ("failed")    printf ("\n")}probe end{        print ("\nClosing down\n")}

相關文章
相關標籤/搜索