1. 流量:
未root的手機(jī)杂曲,需要先獲取pid,然后通過proc獲取uid昼钻,然后通過proc/uid_stat獲取響應(yīng)uid的tcp_send/receive
root的手機(jī)通過/data/system/packages.list獲取對(duì)應(yīng)包名的uid
【查看設(shè)備】
adb
adb ?devices
adb shell
【查看進(jìn)程】
?ps |grep jingdong
cd /proc/27192/net/
?cat dev
2. 內(nèi)存:
Android系統(tǒng)是基于Linux內(nèi)核的,而在Linux系統(tǒng)中析二,所有的進(jìn)程都是init進(jìn)程的子孫進(jìn)程粉洼,也就是說,所有的進(jìn)程都是直接或者間接地由init進(jìn)程fork出來的叶摄。Zygote進(jìn)程也不例外属韧,它是在系統(tǒng)啟動(dòng)的過程,由init進(jìn)程創(chuàng)建的蛤吓。
1. 系統(tǒng)啟動(dòng)時(shí)init進(jìn)程會(huì)創(chuàng)建Zygote進(jìn)程宵喂,Zygote進(jìn)程負(fù)責(zé)后續(xù)Android應(yīng)用程序框架層的其它進(jìn)程的創(chuàng)建和啟動(dòng)工作。
2. Zygote進(jìn)程會(huì)首先創(chuàng)建一個(gè)SystemServer進(jìn)程会傲,SystemServer進(jìn)程負(fù)責(zé)啟動(dòng)系統(tǒng)的關(guān)鍵服務(wù)锅棕,如包管理服務(wù)PackageManagerService和應(yīng)用程序組件管理服務(wù)ActivityManagerService。
3. 當(dāng)我們需要啟動(dòng)一個(gè)Android應(yīng)用程序時(shí)淌山,ActivityManagerService會(huì)通過Socket進(jìn)程間通信機(jī)制裸燎,通知Zygote進(jìn)程為這個(gè)應(yīng)用程序創(chuàng)建一個(gè)新的進(jìn)程。
Dalvik / Native內(nèi)存應(yīng)用:
我們使用的malloc泼疑、C++ new和java new所申請(qǐng)的空間都是heap空間德绿, C/C++申請(qǐng)的內(nèi)存空間在native heap中,而java申請(qǐng)的內(nèi)存空間則在dalvik heap中
通過dumpsys meminfo + 包名能獲得該包當(dāng)前內(nèi)存使用情況:
名詞解釋:
Vss是占用的虛擬內(nèi)存,如果沒有映射實(shí)際的內(nèi)存也算進(jìn)來脆炎。
Rss是占用的物理內(nèi)存梅猿。是共享內(nèi)存+私有內(nèi)存。因?yàn)楣蚕韮?nèi)存是多個(gè)進(jìn)程共用的秒裕,所以存在重復(fù)計(jì)算袱蚓。
Pss是占用的私有內(nèi)存加上平分的共享內(nèi)存。例如一塊1M的共享內(nèi)存被兩個(gè)進(jìn)程共享几蜻,那每個(gè)進(jìn)程分500K喇潘。各進(jìn)程的Pss相加基本等于實(shí)際被使用的物理內(nèi)存,所以這個(gè)經(jīng)常是最重要的參數(shù)梭稚。
Uss是私有內(nèi)存颖低。
Private Clean:?包括該進(jìn)程私有的干凈的內(nèi)存。包括前面說的該進(jìn)程獨(dú)自使用的so和進(jìn)程的二進(jìn)制代碼段弧烤。Clean內(nèi)存的好處是在內(nèi)存緊張時(shí)忱屑,可以釋放物理內(nèi)存。因?yàn)槭莄lean的暇昂,所以不需要寫回到disk莺戒,只需要下次讀取該內(nèi)存(導(dǎo)致缺頁錯(cuò)誤)時(shí)再從disk讀入。
Private Dirty:?表示該進(jìn)程私有的不跟disk數(shù)據(jù)一致的內(nèi)存段
Shared Clean:?公共so組件急波,不會(huì)發(fā)生變化从铲,不用回寫磁盤
Shared Dirty:?Android zygote進(jìn)程的copy-on-write(寫時(shí)拷貝),當(dāng)子進(jìn)程復(fù)用資源澄暮,且無寫入操作時(shí)為share dirty 名段,如果有寫入,則進(jìn)行拷貝泣懊,轉(zhuǎn)為private dirty
數(shù)據(jù)來源:
1. Pss/Shared Dirty/Private Dirty三列是讀取了/proc/process-id/smaps文件獲取的伸辟。它會(huì)對(duì)每個(gè)虛擬內(nèi)存塊進(jìn)行解析,然后生成數(shù)據(jù)馍刮。
2. Native Heap Size/Alloc/Free三列是使用C函數(shù)mallinfo得到的自娩。(C/C++)
3. Dalvik Heap Size/Alloc/Free并非該cpp文件產(chǎn)生,而是android的Debug類生成渠退。
進(jìn)一步查看:
showmap + PID
上述的細(xì)節(jié)
綜上所述:
VSS >= RSS >= PSS >= USS 測試中關(guān)注PSS這個(gè)值即可
VSS牽扯到brk+mmap的內(nèi)存分配機(jī)制,可能分配的內(nèi)存未實(shí)際應(yīng)用
RSS=USS + SharedMem
PSS= USS + SharedMem/Shared count
3. CPU
dumpsys cpuinfo 分母是app uptime - SystemClock.uptimeMillis()脐彩,及當(dāng)前程序運(yùn)行時(shí)間內(nèi)碎乃,是均值
top是經(jīng)典算法,
從top里取得cpu百分比
雖然查詢cpu占用率的工具有很多種惠奸,原理上都是一樣的梅誓,計(jì)算cpu上所有進(jìn)程總的占用率的話依賴于“/proc/stat”文件,計(jì)算單個(gè)進(jìn)程的占用率依賴于“/proc/pid/stat”文件。
us:用戶態(tài)使用的cpu時(shí)間比
sy:系統(tǒng)態(tài)使用的cpu時(shí)間比
ni:用做nice加權(quán)的進(jìn)程分配的用戶態(tài)cpu時(shí)間比
id:空閑的cpu時(shí)間比
wa:cpu等待磁盤寫入完成時(shí)間
hi:硬中斷消耗時(shí)間
si:軟中斷消耗時(shí)間
st:虛擬機(jī)偷取時(shí)間
好了梗掰,下面說說hi和si
如果程序都沒什么問題嵌言,那么是沒有hi和si的,但是實(shí)際上有個(gè)硬中斷和軟中斷的概念及穗。比如硬中斷摧茴,cpu在執(zhí)行程序的時(shí)候,突然外設(shè)硬件(比如硬盤出現(xiàn)問題了)機(jī)器需要立刻通知cpu進(jìn)行現(xiàn)場保存工作埂陆。這個(gè)時(shí)候會(huì)cpu會(huì)出現(xiàn)上下文切換苛白。就是cpu會(huì)有一部分時(shí)間會(huì)被硬中斷占用了,這個(gè)時(shí)間就是hi焚虱。相類似购裙,si是軟中斷的cpu占用時(shí)間,軟中斷是由軟件的指令方式觸發(fā)的鹃栽。
ni
ni是nice的意思躏率,nice是什么呢,每個(gè)linux進(jìn)程都有個(gè)優(yōu)先級(jí)民鼓,優(yōu)先級(jí)高的進(jìn)程有優(yōu)先執(zhí)行的權(quán)利薇芝,這個(gè)叫做pri。進(jìn)程除了優(yōu)先級(jí)外摹察,還有個(gè)優(yōu)先級(jí)的修正值恩掷。即比如你原先的優(yōu)先級(jí)是20,然后修正值為-2供嚎,那么你最后的進(jìn)程優(yōu)先級(jí)為18黄娘。這個(gè)修正值就叫做進(jìn)程的nice值。
對(duì)nice值一個(gè)形象比喻克滴,假設(shè)在一個(gè)CPU輪轉(zhuǎn)中逼争,有2個(gè)runnable的進(jìn)程A和B,如果他們的nice值都為0劝赔,假設(shè)內(nèi)核會(huì)給他們每人分配1k個(gè)cpu時(shí)間片誓焦。但是假設(shè)進(jìn)程A的為0,但是B的值為-10着帽,那么此時(shí)CPU可能分別給A和B分配1k和1.5k的時(shí)間片杂伟。故可以形象的理解為,nice的值影響了內(nèi)核分配給進(jìn)程的cpu時(shí)間片的多少仍翰,時(shí)間片越多的進(jìn)程赫粥,其優(yōu)先級(jí)越高,其優(yōu)先級(jí)值(PRI)越低予借。%nice越平,就是改變過優(yōu)先級(jí)的進(jìn)程的占用CPU的百分比频蛔,如上例中就是0.5k/2.5k=1/5=20%。
wa
wa指的是CPU等待磁盤寫入完成的時(shí)間秦叛,就是說前提是要進(jìn)行IO操作晦溪,在進(jìn)行IO操作的時(shí)候,CPU等待時(shí)間挣跋。比如上面那個(gè)程序三圆,最后一步,從系統(tǒng)空間到dst硬盤空間的時(shí)候浆劲,如果程序是阻塞的嫌术,那么這個(gè)時(shí)候cpu就要等待數(shù)據(jù)寫入磁盤才能完成寫操作了。所以這個(gè)時(shí)候cpu等待的時(shí)間就是wa牌借。
st
st的名字很生動(dòng)度气,偷取。膨报。磷籍。是專門對(duì)虛擬機(jī)來說的,一臺(tái)物理是可以虛擬化出幾臺(tái)虛擬機(jī)的现柠。在其中一臺(tái)虛擬機(jī)上用top查看發(fā)現(xiàn)st不為0院领,就說明本來有這么多個(gè)cpu時(shí)間是安排給我這個(gè)虛擬機(jī)的,但是由于某種虛擬技術(shù)够吩,把這個(gè)cpu時(shí)間分配給了其他的虛擬機(jī)了比然。這就叫做偷取。
id?
剩下的id就是除了上面那么多cpu處理上下文以外的cpu時(shí)間片周循。當(dāng)然在這些時(shí)間片上强法,cpu是空閑的。
1.1 /proc/stat文件分析
我們?cè)贚inux Shell環(huán)境中使用cat命令查看/proc/stat文件湾笛。
該文件顯示的第一行就是cpu總體的使用情況饮怯,每列數(shù)值是后面幾行邏輯處理器每列數(shù)據(jù)的相加值,可見該cpu共有4個(gè)邏輯處理器(Processor)嚎研,我們也可以通過/proc/cpuinfo文件去查看該Linux內(nèi)核的cpu具體情況蓖墅。我們依據(jù)Linux用戶手冊(cè)詳細(xì)看下第一行cpu數(shù)據(jù)的每列數(shù)據(jù)代表的含義。
1)這些數(shù)值的單位都是 jiffies临扮,jiffies 是內(nèi)核中的一個(gè)全局變量论矾,用來記錄系統(tǒng)啟動(dòng)以來產(chǎn)生的節(jié)拍數(shù),在 Linux 中杆勇,一個(gè)節(jié)拍大致可以理解為操作系統(tǒng)進(jìn)程調(diào)度的最小時(shí)間片拇囊,不同的 Linux 系統(tǒng)內(nèi)核這個(gè)值可能不同,通常在 1ms 到 10ms 之間靶橱。
2)cpu 552 56 1496 266573 652 0 224 0 0 0 (以此行為例)
user(552)?Time spent in user mode.
從系統(tǒng)啟動(dòng)開始累積到當(dāng)前時(shí)刻,處于用戶態(tài)的運(yùn)行時(shí)間,不包含 nice 值為負(fù)的進(jìn)程关霸。
nice(56)?Time spent in user mode with low priority(nice).
系統(tǒng)啟動(dòng)開始累積到當(dāng)前時(shí)刻传黄,nice 值為負(fù)的進(jìn)程所占用的 CPU 時(shí)間。Nice值是類UNIX操作系統(tǒng)中表示靜態(tài)優(yōu)先級(jí)的數(shù)值队寇。 每個(gè)進(jìn)程都有自己的靜態(tài)優(yōu)先級(jí)膘掰,優(yōu)先級(jí)高的進(jìn)程得以優(yōu)先運(yùn)行。
system(1496)?Time spent in system mode.
從系統(tǒng)啟動(dòng)開始累積到當(dāng)前時(shí)刻佳遣,處于核心態(tài)的運(yùn)行時(shí)間识埋。
idle(266573)?Time spent in the idle task.
從系統(tǒng)啟動(dòng)開始累積到當(dāng)前時(shí)刻,除 IO 等待時(shí)間以外的其他等待時(shí)間零渐。
iowait(652)?Time waiting for I/O to complete.
從系統(tǒng)啟動(dòng)開始累積到當(dāng)前時(shí)刻窒舟,IO 等待時(shí)間。(since 2.5.41诵盼,內(nèi)核版本惠豺,下同)
irq(0)?Time servicing interrupts.
從系統(tǒng)啟動(dòng)開始累積到當(dāng)前時(shí)刻,服務(wù)中斷時(shí)間风宁。(since 2.6.0-test4)
softirq(224)?Time servicing softirqs.
從系統(tǒng)啟動(dòng)開始累積到當(dāng)前時(shí)刻洁墙,軟中斷時(shí)間。(since 2.6.0-test4)
stealstolen(0)?Stolen time, which is the time spent in other operating systems when running in a virtualized environment.
從系統(tǒng)啟動(dòng)開始累積到當(dāng)前時(shí)刻戒财,在虛擬環(huán)境運(yùn)行時(shí)花費(fèi)在其他操作系統(tǒng)的時(shí)間热监。(since 2.6.11)
guest(0)?Which is the time spent running a virtual CPU for guest operating systems under the control of the Linux kernel.
從系統(tǒng)啟動(dòng)開始累積到當(dāng)前時(shí)刻,在Linux內(nèi)核控制下的操作系統(tǒng)虛擬cpu花費(fèi)的時(shí)間饮寞。(since 2.6.24)
guest_nice?Time spent running a niced guest (virtual CPU for guest operating systems under the control of the Linux kernel).
從系統(tǒng)啟動(dòng)開始累積到當(dāng)前時(shí)刻孝扛,在Linux內(nèi)核控制下的操作系統(tǒng)虛擬cpu花費(fèi)在nice進(jìn)程上的時(shí)間。(since Linux 2.6.33)
CPU總體占用率:
cpu總的使用時(shí)間計(jì)算如下:
totalCPUTime = user + nice + system + idle + iowait + irq + softirq + stealstolen + guest + guest_nice
通常我們都會(huì)選擇較短的時(shí)間進(jìn)行取樣兩次cpu數(shù)據(jù)1和2骂际。
常用cpu占用率方法可描述為:
totalCPUrate = (非空閑cpu時(shí)間2-非空閑cpu時(shí)間1)/(cpu總時(shí)間2-cpu總時(shí)間1)x100%
換成變量描述為:
totalCPUrate =( (totalCPUTime2-idle2)-(totalCPUTime1-idle1))/(totalCPUTime2-totalCPUTime1)x100%
/proc/<pid>/stat與應(yīng)用程序cpu占有率的計(jì)算:
/proc/<pid>/stat文件分析
我們?cè)贚inux Shell環(huán)境中使用cat命令查看/proc//stat文件疗琉。我們可以先通過top命令獲得目標(biāo)應(yīng)用的進(jìn)程id。
pid=1378 進(jìn)程號(hào)
utime=1286 該任務(wù)在用戶態(tài)運(yùn)行的時(shí)間歉铝,單位為jiffies
stime=1854 該任務(wù)在核心態(tài)運(yùn)行的時(shí)間盈简,單位為jiffies
cutime=6 所有已死線程在用戶態(tài)運(yùn)行的時(shí)間,單位為jiffies
cstime=2 所有已死在核心態(tài)運(yùn)行的時(shí)間太示,單位為jiffies
應(yīng)用程序cpu的使用時(shí)間計(jì)算如下:
processCPUTime = utime + stime
processCPUrate = ( processCPUTime2 – processCPUTime1) / (totalCPUTime2 – totalCPUTime1) x100%
4. 啟動(dòng)時(shí)間
adb shell am start -W $packageName/$activityName
shell@natrium:/ $ am start -W com.android.calendar/.homepage.AllInOneActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.android.calendar/.homepage.AllInOneActivity }
Status: ok
Activity: com.android.calendar/.homepage.AllInOneActivity
ThisTime: 77
TotalTime: 77
WaitTime: 92
Complete
adb shell?am force-stop com.android.calendar
如此循環(huán)
5. App幀率
SurfaceFlinger 是 Android 的一個(gè)服務(wù)柠贤,運(yùn)行在 Android 的System 進(jìn)程中,負(fù)責(zé)管理系統(tǒng)的幀緩沖區(qū)类缤,繪制應(yīng)用程序的UI臼勉。Android應(yīng)用程序會(huì)請(qǐng)求SurfaceFlinger服務(wù)創(chuàng)建Surface,在上面繪制自己的UI餐弱,然后將這個(gè)已經(jīng)繪制好了UI的Surface渲染到設(shè)備顯示屏上去
清空緩存:
adb shell dumpsys SurfaceFlinger --laten
在開發(fā)者選項(xiàng)中有個(gè)“ GPU呈現(xiàn)模式分析(Profile GPU rendering宴霸,計(jì)算adb shell dumpsys gfxinfo中的呈現(xiàn)時(shí)間)”功能囱晴,在開啟這個(gè)功能后,系統(tǒng)就會(huì)記錄保留每個(gè)界面最后128幀圖像繪制的相關(guān)時(shí)間信息瓢谢。在開啟這個(gè)功能后畸写,重新啟動(dòng)APP,滑動(dòng)頁面然后執(zhí)行adb命令氓扛。
db shell dumpsys $packageName
Draw:表示在Java中創(chuàng)建顯示列表部分中枯芬,OnDraw()方法占用的時(shí)間。
Process:表示渲染引擎執(zhí)行顯示列表所花的時(shí)間采郎,view越多千所,時(shí)間就越長
Execute:表示把一幀數(shù)據(jù)發(fā)送到屏幕上排版顯示實(shí)際花費(fèi)的時(shí)間。其實(shí)是實(shí)際顯示幀數(shù)據(jù)的后臺(tái)緩存區(qū)與前臺(tái)緩沖區(qū)交換后并將前臺(tái)緩沖區(qū)的內(nèi)容顯示到屏幕上的時(shí)間蒜埋。
Draw + Process + Execute?= 完整顯示一幀 淫痰,這個(gè)時(shí)間要小于16ms才能保存每秒60幀。
定期清零重新記錄理茎,避免如何分清哪些數(shù)據(jù)是上次的黑界。命令: dumpsys SurfaceFlinger --latency-clear