Android?終端性能測(cè)試——內(nèi)存篇
做Android QQ性能測(cè)試時(shí),內(nèi)存測(cè)試中遇到不少困惑,”各種”內(nèi)存術(shù)語(yǔ),到底什么意思,怎么獲取,這里總結(jié)一下。
進(jìn)行的內(nèi)存測(cè)試主要有兩個(gè)方面,一,OOM的發(fā)現(xiàn)和定位,二,同歷史版本或競(jìng)品的對(duì)比測(cè)試。關(guān)于oom可以用MAT進(jìn)行分析,具體分析方法參見(jiàn)susanwu在km上的文章《如何使用Memory_Analyzer分析內(nèi)存泄漏》。下面主要總結(jié)一下Android性能?測(cè)試中常用的方法及解釋
一:running services"查看service進(jìn)程內(nèi)存
從Android 2.0開(kāi)始,在Settings中加入了一個(gè)新的activity("Running Services" activity),它用于顯示當(dāng)前運(yùn)行的每個(gè)Services進(jìn)程的內(nèi)存使用情況及整個(gè)手機(jī)的內(nèi)存大致使用情況??梢酝ㄟ^(guò)Setting->Applications->Running services進(jìn)入該activity。
使用該方法需要注意,一些應(yīng)用程序可能有幾個(gè)進(jìn)程,但是在這里只顯示了其中的某個(gè)進(jìn)程。比如微信,在Running services activity?只能看到子進(jìn)程com.tencent.mm:push的內(nèi)存信息,所以,這個(gè)統(tǒng)計(jì)有時(shí)候是不可靠的。
二:常用的shell命令獲?。?/p>
1.??????Procrank命令,Procrank?可以同時(shí)獲得以下幾種內(nèi)存的信息:
need-to-insert-img
l??VSS:Virtual Set Size?虛擬耗用內(nèi)存(包含共享庫(kù)占用的內(nèi)存)。This size also includes memory that may not be resident in RAM like mallocs that have been allocated but not written to,所以用VSS來(lái)衡量一個(gè)進(jìn)程實(shí)際使用的內(nèi)存意義不大。
l??RSS :? Resident Set Size?實(shí)際使用物理內(nèi)存(包含共享庫(kù)占用的內(nèi)存)。?RSS can be misleading, because it reports the total all of the shared libraries that the process uses, even though a shared library is only loaded into memory once regardless of how many processes use,所以用RSS來(lái)衡量進(jìn)程占用的內(nèi)存信息不是特別準(zhǔn)確。
l??PSS?- Proportional Set Size?實(shí)際使用的物理內(nèi)存(比例分配共享庫(kù)占用的內(nèi)存)。?PSS is a very useful number because when the PSS for all processes in the system are summed together, that is a good representation for the total memory usage in the system,所以用pss衡量程序占用的內(nèi)存誤差比較小。
l??USS?- Unique Set Size?進(jìn)程獨(dú)自占用的物理內(nèi)存(不包含共享庫(kù)占用的內(nèi)存).USS is an extremely useful number because it indicates the true incremental cost of running a particular process,所以用USS描述進(jìn)程占用內(nèi)存的波動(dòng)和峰值比較有意義。
一般存在以下關(guān)系VSS>=RSS>=PSS>=USS。
如果要獲得某個(gè)進(jìn)程的內(nèi)存信息,用procrank是個(gè)不錯(cuò)的選擇,但是目前很多android系統(tǒng)都不支持這個(gè)命令,HTC手機(jī)部分原生系統(tǒng)支持,比如g3的2.2.1rom。
2.?????Top命令
輸入命令行adb shell top,輸出如下圖所示:列出top*進(jìn)程的cpu和內(nèi)存占用情況,默認(rèn)按照cpu占用降序排列。top可以獲得進(jìn)程的VSS和RSS信息,命令持續(xù)的監(jiān)視,所以個(gè)人覺(jué)得這是一個(gè)快速查看進(jìn)程內(nèi)存和cpu的好方法。
need-to-insert-img
3.?????Ps命令
PS命令可以獲得應(yīng)用程序的VSIZE(VSS)和RSS,PS是一個(gè)獲得的是應(yīng)用的瞬間狀態(tài),不需要退出確認(rèn),因此在自動(dòng)化腳本上比較好用。ps | grep appName直接輸出appName進(jìn)程對(duì)應(yīng)的內(nèi)存信息。
need-to-insert-img
4.?????dumpsys meminfo
dumpsys?用來(lái)給出手機(jī)中所有應(yīng)用程序的信息,并且也會(huì)給出手機(jī)的狀態(tài)。用以下命令可以查看程序的內(nèi)存使用情況:adb shell dumpsys meminfo $package_name or $pid??? ??//使用程序的包名或者進(jìn)程id
下圖是查看pid為767的應(yīng)用內(nèi)存信息截圖。
need-to-insert-img
android程序內(nèi)存被分為2部分:native和dalvik,dalvik就是我們平常說(shuō)的java堆,我們創(chuàng)建的對(duì)象是在這里面分配的,而bitmap是直接在native上分配的,對(duì)于內(nèi)存的限制是native+dalvik不能超過(guò)最大限制。android程序內(nèi)存一般限制在16M和24M
size?:總內(nèi)存大?。╧b)。
Allocated:表示的是已使用了的內(nèi)存大?。╧b),
Free:表示的是剩余的內(nèi)存大小(kb)
PrivateDirty:非共享的,又不能換頁(yè)出去(can not be paged to disk?)的內(nèi)存的大小。和USS相似,但是實(shí)際實(shí)踐中,發(fā)現(xiàn)他們還是有細(xì)微的差別,現(xiàn)在還沒(méi)有搞明白。
SharedDirty:參照PrivateDirty我認(rèn)為它應(yīng)該是指共享的,又不能換頁(yè)出去(can not be paged to disk?)的內(nèi)存的大小。比如Linux為了提高分配內(nèi)存速度而緩沖的小對(duì)象,即使所有共享它的進(jìn)程結(jié)束,該內(nèi)存也不會(huì)釋放掉,它只是又重新回到緩沖中而已。
5.?????adb shell cat /proc/meminfo
該方式只能得出系統(tǒng)整個(gè)內(nèi)存的大概使用情況。
need-to-insert-img
MemTotal?:可供系統(tǒng)和用戶使用的總內(nèi)存大小?(它比實(shí)際的物理內(nèi)存要小,因?yàn)檫€有些內(nèi)存要用于radio, DMA buffers,?等).?
MemFree:剩余的可用內(nèi)存大小。這里該值比較大,實(shí)際上一般Android system?的該值通常都很小,因?yàn)槲覀儽M量讓進(jìn)程都保持運(yùn)行,這樣會(huì)耗掉大量?jī)?nèi)存。
Cached:?系統(tǒng)用于文件緩沖等的內(nèi)存.?通常systems需要20MB?以避免bad paging states。
6.?????cat /proc/$pid/status
以下是進(jìn)程ID為767的應(yīng)用程序的status,其中state可以看出該應(yīng)用目前的狀態(tài)sleeping或running等。
need-to-insert-img
VmSize(KB)?:任務(wù)虛擬地址空間的大小(total_vm-reserved_vm),其中total_vm為進(jìn)程的地址空間的大小,reserved_vm:進(jìn)程在預(yù)留或特殊的內(nèi)存間的物理頁(yè)
VmLck(KB)?
:任務(wù)已經(jīng)鎖住的物理內(nèi)存的大小。鎖住的物理內(nèi)存不能交換到硬盤(pán)
VmRSS(KB):
應(yīng)用程序正在使用的物理內(nèi)存的大小,和RSS值基本相同
KeyEvent?ValueKEYCODEComment
0KEYCODE_UNKNOWN?
1KEYCODE_MENU在SDK2.1的模擬器中命令失效,sendevent命令可行
2KEYCODE_SOFT_RIGHT?
3KEYCODE_HOME?
4KEYCODE_BACK?
5KEYCODE_CALL?
6KEYCODE_ENDCALL?
7KEYCODE_0?
8KEYCODE_1?
9KEYCODE_2?
10KEYCODE_3?
11KEYCODE_4?
12KEYCODE_5?
13KEYCODE_6?
14KEYCODE_7?
15KEYCODE_8?
16KEYCODE_9?
17KEYCODE_STAR?
18KEYCODE_POUND?
19KEYCODE_DPAD_UP?
20KEYCODE_DPAD_DOWN?
21KEYCODE_DPAD_LEFT?
22KEYCODE_DPAD_RIGHT?
23KEYCODE_DPAD_CENTER?
24KEYCODE_VOLUME_UP?
25KEYCODE_VOLUME_DOWN?
26KEYCODE_POWER?
27KEYCODE_CAMERA?
28KEYCODE_CLEAR?
29KEYCODE_A?
30KEYCODE_B?
31KEYCODE_C?
32KEYCODE_D?
33KEYCODE_E?
34KEYCODE_F?
35KEYCODE_G?
36KEYCODE_H?
37KEYCODE_I?
38KEYCODE_J?
39KEYCODE_K?
40KEYCODE_L?
41KEYCODE_M?
42KEYCODE_N?
43KEYCODE_O?
44KEYCODE_P?
45KEYCODE_Q?
46KEYCODE_R?
47KEYCODE_S?
48KEYCODE_T?
49KEYCODE_U?
50KEYCODE_V?
51KEYCODE_W?
52KEYCODE_X?
53KEYCODE_Y?
54KEYCODE_Z?
55KEYCODE_COMMA?
<td style="padding:0pt 5.4pt;width:96.35pt" valign="bottom"