Android應用性能分析

原文出自:http://www.geek521.com/?p=3705

其實主要是內存方面,內存管理是個永恆的話題!

1.從工具DDMS中,在Sysinfo的tab欄裏面有一個Memory usage的選項,通過USB連接Android設備以後很容易抓到圖。
在圖中可以看到系統隨時可以用的內存是Free和Buffers兩項,因爲我抓圖的系統只有128M的內存,所以看上去這部分可用內存已經很少了。

2.通過Linux的/proc文件系統的meminfo來分析這個系統的內存使用情況更客觀。之所以這麼說,是因爲通過這種方法可以繞開繁瑣的dalvik實現機制,以系統的層面來分析:

C:\Users\Administrator>adb shell
shell@android:/ $ cat /proc/meminfo
cat  /proc/meminfo
MemTotal:         999008 kB
MemFree:          157532 kB
Buffers:              41308 kB
Cached:             319584 kB
SwapCached:            0 kB
Active:               488128 kB
Inactive:            167012 kB
Active(anon):     292356 kB
Inactive(anon):     3544 kB
Active(file):       195772 kB
Inactive(file):    163468 kB
Unevictable:        1520 kB
Mlocked:           13684 kB
HighTotal:         529408 kB
HighFree:          61680 kB
LowTotal:          469600 kB
LowFree:           95852 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:        295816 kB
Mapped:            165768 kB
Shmem:               360 kB
Slab:                  27752 kB
SReclaimable:       9524 kB
SUnreclaim:        18228 kB
KernelStack:        8232 kB
PageTables:         9628 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:       499504 kB
Committed_AS:    5690380 kB
VmallocTotal:      540672 kB
VmallocUsed:      139020 kB
VmallocChunk:      98112 kB
shell@android:/ $

 

對於Linux系統來說,可以立即使用的內存是 MemFree+Buffers+Cache,

我們從DDMS中拿到的圖差很多。或者說Google隱藏了cache,沒有給我我想要的東西;Android系統爲了加快系統的運行速度會在系統允許的情況下,大量的使用內存作爲應用程序的cache。而當系統內存緊張的時候,會首先釋放cache的內存,

3、Android內存介紹:
在java開發過程中,是通過new來爲對象分配內存的,而內存的釋放是由垃圾收集器(GC)來回收的,在開發的過程中,不需要顯式的去管理內存,java虛擬機會自動幫我們回收內存。但是這樣有可能在不知不覺中就會浪費了很多內存,最終導致java虛擬機花費很多時間去進行垃圾回收,更嚴重的是造成JVM的OOM。
4、APP佔用的內存分哪些:
Android系統中的內存和linux系統一樣,存在着大量的共享內存。每個APP佔內存會有私有和公共的兩部分:ShareDirty、PrivateDirty。Pss是考慮共享內存的內核計算尺度 — 基本上一個進程的每個內存頁面被按一個比率縮減,這個比率和同樣使用該頁面的其他進程的數量有關。理論上你可以累計所有進程的Pss佔用量來檢查所有進程的內存佔用量,也可以比較進程的Pss來大致發現進程各自的權重。PrivateDirty,它基本上是進程內不能被分頁到磁盤的內存,也不和其他進程共享。
手機中系統設置裏有可以查看正在運行的應用程序所佔的內存,此處顯示的內存爲該進程所佔用的Total Pss。所以我們只需要查看Total Pss的值就可以知道該應用運行時所佔的內存的大小。
5、如何查看一個APP佔用的內存,查看內存大致上有三種方法:
1. 通過系統設置查看
在系統設置中->應用->正在運行->APP
優點:操作簡單
缺點:數值不準確,無法實時查看數值變化
2. 通過命令行查看
adb shell dumpsys meminfo  yourpakagename
其中Pss對應的TOTAL值爲內存所實際佔用的值
優點:簡單方便,數據全面精確
缺點:無法實時查看內存佔用
3. 通過系統API查看
首先通過activitymanager獲得正在運行的程序列表,找到所要獲取的程序的pid。
activitymanager.getRunningAppProcesses()
再通過memoryinfo[0].getTotalPss();方法獲得實際內存佔用
Memoryinfo中還包括getTotalPrivateDirty和getTotalSharedDirty方法
優點:可拓展性高,可以通過程序實時查看內存的佔用;數據全面精確
缺點:需要具有開發能力,入手較爲困難,所以我們現在在測試內存的時候,是使用了內部自己研發的一款APP來監測內存的,這個APP目前可以實現實時監測並記錄數據結果,可以提供給開發者和測試者分析內存的數據支持。目前仍然屬於內測階段,以後有機會可以提供給大家使用。
四、內存泄漏
何爲內存泄漏?內存泄漏也稱作“存儲滲漏”,用動態存儲分配函數動態開闢的空間,在使用完畢後未釋放,結果導致一直佔據該內存單元,直到程序結束。
內存泄漏的實例:
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
for (int i = 0; i < 100; i++) {
ImageView img = new ImageView(MainActivity.this);
img.setImageResource(R.drawable.ic_launcher);

test.add(img);
}
}
});
其中test爲靜態的List<ImageView>。這樣,如果一直點擊btn就會出現內存泄漏的情形。
我們如何去監測內存泄漏呢?
以上面內存泄漏的例子爲測試Activity,當點擊按鈕後,會向一個靜態數組中添加圖片,這樣就形成了一個內存泄漏的場景。
進入測試Activity,在點擊按鈕前先記錄當前APP所佔用的內存,然後點擊按鈕。等待操作執行完成後,進行一次GC,再查看APP所佔用的內存。
返回後APP所佔用的內存沒有明顯的回落,表明在代碼中可能存在內存泄漏的情況發生。
即:在執行某種操作後進行一次GC,內存沒有明顯的回落。此時即可以斷定代碼中可能存在內存泄漏。
檢測方法:
通過上文所用的三種方法去查看內存的使用情況
使用DDMS中的Heap:
1)      打開DDMS並打開Devices視圖和Heap視圖
2)      點擊選擇要監控的進程
3)      選中Devices視圖界面上的”update heap” 圖標
4)      點擊Heap視圖中的”Cause GC” 按鈕(相當於進行了一次GC的操作)
一般我們會觀察Data Object的Total值,正常情況下在每次GC後,這個值都會有明顯的回落並會穩定在一個範圍之內,說明代碼中沒有未被釋放的內存;若這個值在每次GC後沒有出現明顯的回落,則說明代碼中可能存在沒有被釋放的內存。
總述:內存不僅是性能測試時需要關注的,作爲優秀的開發工程師更應該關注自己的代碼內存佔用的情況,這樣可以儘量避免OOM的情況發生。要知道手機分配給每個進程的內存並不多,當系統內存不夠的時候會kill掉一些佔內存高的進程,所以爲了不被系統kill掉我們要儘可能的合理使用內存避免內存泄漏的情況發生。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章