【Android Linux內存及性能優化】(八) 系統性能分析工具

本文接着
【Android Linux內存及性能優化】(一) 進程內存的優化 - 堆段
【Android Linux內存及性能優化】(二) 進程內存的優化 - 棧段 - 環境變量 - ELF
【Android Linux內存及性能優化】(三) 進程內存的優化 - ELF執行文件的 數據段-代碼段
【Android Linux內存及性能優化】(四) 進程內存的優化 - 動態庫- 靜態庫
【Android Linux內存及性能優化】(五) 進程內存的優化 - 線程
【Android Linux內存及性能優化】(六) 系統內存的優化
【Android Linux內存及性能優化】(七) 程序內存泄漏檢查工具

二、系統性能分析

2.1 性能分析

程序性能的問題,有很多原因,需要對症下藥。
導致軟件性能低下,主要有下面3種原因:

  1. 程序的運算量很大,導致CPU 過於繁忙,CPU 是瓶頸。
    可以運行 top 命令,如果某個進程的CUP 利用率很高,則說明CPU 是性能瓶頸。

  2. 程序需要大量的I/O ,讀寫文件、內存操作等,CPU 更多的是處於等待,I/O 部分成爲程序性能瓶頸。
    對於大量I/O 引起的程序性能問題,可以學習這篇文章: 《使用異步 I/O 大大提高應用程序的性能

  3. 程序之間相互等待,結果CPU 利用率很低,但運行速度依然很慢,程序間的共享與死鎖制約了程序的性能。
    如果系統的CPU 利用率並不高,而且也不存在大量的I/O 操作,那麼很有可能是多個線程之間相互等待造成的,這時就需要對程序進行大規模的重構。


2.1.1 /proc 目錄

通過proc 目錄,能夠了解到CPU 和I/O 設備的工作狀況,從而能夠幫助分析導致程序性能低下的原因。


2.1.1.1 系統相關 cat /proc/stat

ciellee@sh:~$ cat /proc/stat 
累計時間  user  nice system   idle   iowait  irq  softirq
cpu  3167348 29348 1381731 80468196 1075970 0 101955 0 0 0
cpu0 397571 3476 157335 10150112 70357 0 35871 0 0 0
cpu1 372224 3435 174119 10136025 51305 0 16722 0 0 0
cpu2 418781 3775 195023 10131454 32896 0 7197 0 0 0
cpu3 381767 4442 166107 10172208 33756 0 14511 0 0 0
cpu4 376322 3423 160088 10192147 30325 0 3210 0 0 0
cpu5 388663 3460 158360 10202394 29673 0 4082 0 0 0
cpu6 435006 3761 212003 9410045 713497 0 5559 0 0 0
cpu7 397011 3573 158693 10073807 114157 0 14800 0 0 0
intr 185329212 9 479 0 0 0 0 0 0 1 5007429 0 0 0 0 0 0 0 60384 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1954
ctxt 550116756
btime 1590973874
processes 536879
procs_running 1
procs_blocked 0
softirq 198450776 16075871 60900311 42960 3505868 1818711 0 1749208 63006387 0 51351460

CPU 後面數值分別代表着CPU 在不同狀態下所用的時間,其單位爲 jiffy (0.01s),7個數值的含義分別是:

  • user :從系統啓動開始累計到當前的時間,用戶態的CPU 時間,不包含 nice 值爲負的進程。
  • nice :從系統啓動開始累計到當前時刻,nice 值爲負的進程所佔用的CPU 時間。
  • system :從系統啓動開始累計到當前時刻,內核所佔用的CPU 時間
  • idle :從系統啓動開始累計到當前時刻,除硬盤 IO 等待時間以外其他等待時間。
  • iowait :比系統啓動開始累計到當前時刻,硬盤IO 等待時間。
  • irq :從系統啓動開始累計到當前時刻,硬中斷時間。
  • softirq :從系統啓動開始累計到當前時刻,軟中斷時間。

由此可以推導出:
CPU 時間 = user + nice + idle + iowait + irq + softirq
CPU 的利用率 = 1 - (idle)/(user + system + nice + iowait + irq + softirq)

根據CPU 的利用率,可以知道當前系統的CPU 負載情況。

從這些數據,可以知道分析性能瓶頸在哪裏:

  1. 程序代碼有問題,導致佔用了大量的CPU ,可以計算CPU 用戶態利用率
    CPU 用戶態利用率 = (user + nice)/(user + system + nice + idle + iowait + irq + softirq)

  2. 程序代碼調用了大量的系統調用,導致Linux 內核佔用了大量的CPU
    CPU 內核態利用率 = (system)/(user + system + nice + idle + iowait + irq + softirq)

  3. 系統和Flash 、內存等 有大量的交互和等待,從而導致系統性能下降
    IO 利用率 = (iowait)/(user + system + nice + idle + iowait + irq + softirq)


2.1.1.2 系統相關 cat /proc/loadavg

ciellee@sh:~$ cat /proc/loadavg
1.97 2.14 1.74 2/1048 6774

上面數字中:
1.97 	:	1分鐘平均負載
2.14 	:	5分鐘平均負載
1.74 	:	15分鐘平均負載
2		:	在採樣時刻,運行隊列的任務的數量,與/proc/stat 的procs_running 表示相同意思
1048 	:	在採樣時刻,系統中活躍的任務的個數(不包括運行已經結束的任務)
6774	:	最大的 PID 值,包括輕量級進程,即線程

2.1.1.3 進程相關 cat /proc/51/stat

ciellee@sh:~$ cat /proc/51/stat
51 (migration/7) S 2 0 0 0 -1 69238848 0 0 0 0 0 11 0 0 
-100 0 1 0 4 0 0 18446744073709551615 0 0 0 0 0 0 0 
2147483647 0 0 0 0 17 7 99 1 0 0 0 0 0 0 0 0 0 0 0

每個參數解析如下;
pid = 50 				進程(線程)pid號
comm = migration		應用程序或命名的名字
task_state=S			任務的狀態:R:running,S:sleeping,D:disk sleep,
								  T:stopped,T:tracing stop,Z:zombie,X:dead
ppid = 2				父進程ID
pgid = 0				線程組號
sid = 0					該任務所在的會話組ID
ttnr = 0				該任務的tty終端的設備號,
tty_pgrp = -1 			終端的進程組號,當前運行在該任務所在終端的前臺任務(包括 shell 應用程序)的pid
task->flags = 69238848	進程標誌位,查看該任務的特性
min_flt = 0				該任務不需要從硬盤拷數據而發生的缺頁(次缺頁)次數
cmin_flt = 0			累計的該任務的所有的waited-for 進程曾經發生的次缺頁的數目
maj_flt = 0				該任務需要從硬盤拷數據而發生的缺頁(主缺頁)次數
cmaj_flt = 0			累計的該任務的所有的waited-for 進程曾經發生的主缺頁的數目
utime = 0				該任務在用戶態運行的時間,單位爲 jiffy
stime = 11				該任務在覈心態運行的時間,單位爲 jiffy
cutime = 0 				累計的該任務的所有的waited-for 進程曾經在用戶態運行的時間,單位爲 jiffy
cstime = 0				累計的該任務的所有的waited-for 進程曾經在覈心態運行的時間,單位爲 jiffy
priority = -100			任務的動態優先級
nice = 0				任務的靜態優先級
num_threads = 1			該任務所在的線程組裏線程的個數
it_real_value = 0		由於計時間隔導致下一個SIGALRM 發送進程的時延,以jiffy 爲單位
start_time = 4			該任務的啓動的時間,單位爲 jiffy
vsize = 0				該任務的虛擬地址空間大小
rss = 0(page)			該任務當前駐留虛擬地址空間的大小
vsize = 18446744073709551615(bytes)	該任務的虛擬空間大小
rss = 0(page)			該任務當前駐留物理地址空間的大小
rlim = 0(bytes)			該任務能駐留物理地址空間的最大值
start_code = 0			該任務在虛擬地址空間的代碼段的起始地址
end_code = 0			該任務在虛擬地址空間的代碼段的結束地址
start_stack = 0			該任務在虛擬地址空間的棧的結束地址
kstkesp = 0				esp(32位堆棧指針)的當前值,與在進程的內核堆棧頁得到的一致	
kstkeip = 0				指向將要執行的指令的指針,EIP(32位指令指針)的當前值
pendingsig = 2147483647	待處理信號的位圖,記錄發產送給進程的普通信號
block_sig = 0			阻塞信號的位圖
sigign = 0				忽略的信號的位圖
sigcatch = 0			被俘獲的信號的位圖
wchan = 0				如果該進程是睡眠狀態,該值給出調度的調用點
nswap = 17				被 swapped 的頁數,當前沒用
cnswap = 7				所有子進程被swapped 的頁數和,當前沒用
exit_signal = 99		該進程結束時,向父進程所發送的信號
task_cpu(task) = 1		運行在哪個CPU 上
task_rt_priority = 0	實時進程的相對優先級別
task_policy = 0			進程的調度策略,0:非實時進程,1:FIFO實時進程,2:RR實時進程

通過文件stat 的utime, stime, cutime 和 cstime 的數值,能夠計算出進程的CPU 佔用率。

要想獲得CPU 佔用率,需要兩個採樣點:
採樣點1: 系統時間記爲 sys1, 進程時間分別爲:utime1,stime1,cutime1,cstime1
採樣點2: 系統時間記爲 sys2, 進程時間分別爲:utime2,stime2,cutime2,cstime2

進程CPU 佔用率 = ( (utime2 + stime2 - cutime2 - stime2) - (utime1 + stime1 - cutime1 - stime1) ) / (sys2 - sys1)
進程用戶態佔用率 = ( (utime2 - cutime2) - (utime1 - cutime1) ) / (sys2 - sys1)
進程內核態佔用率 = ( (stime2 - stime2) - (stime1 - stime1) ) / (sys2 - sys1)


2.1.1.4 進程相關 top

top 是最常用來監控系統範圍內進程活動的工具,它提供運行在系統上的與CPU 關係最密切的進程列表,以及許多有意義的統計值(如負載平均,進程數量 以及 使用的 存儲器和頁面空間的數量)。

Tasks: 302 total,   1 running, 229 sleeping,   0 stopped,   0 zombie
%Cpu(s):  3.7 us,  1.6 sy,  0.0 ni, 93.2 id,  1.3 wa,  0.0 hi,  0.1 si,  0.0 st
KiB Mem : 16281312 total,  2675480 free,  2865172 used, 10740660 buff/cache
KiB Swap: 16605180 total, 16598768 free,     6412 used. 12037752 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                           
 3571 ciellee   20   0 2139236 191748  40460 S  23.5  1.2  96:04.80 compiz                                                                            
 1141 root      20   0  580232 185248 137744 S  17.6  1.1  41:17.93 Xorg                                                                              
 3315 ciellee   20   0  827724 302988  15876 S  11.8  1.9   1:40.13 hud-service                                                                       
 3515 ciellee   20   0 2036500 104556  49964 S  11.8  0.6   1:17.75 nautilus                                                                          
 2521 ciellee   20   0 2951112 209128  36744 S   5.9  1.3 112:49.49 WeChat.exe                                                                        
 3270 ciellee   20   0  516464  48528  18988 S   5.9  0.3   0:23.38 bamfdaemon                                                                        
 3341 ciellee   20   0  704340 120900  24328 S   5.9  0.7   7:01.88 unity-panel-ser                                                                   
24020 ciellee   20   0   24928   4140   3404 R   5.9  0.0   0:00.03 top                                                                               
    1 root      20   0  175892   5764   3220 S   0.0  0.0   0:03.46 systemd                                                                           
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.13 kthreadd                                                                          
    4 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 kworker/0:0H                                                                      
    6 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 mm_percpu_wq
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章