Android記憶體分析工具(四):adb命令
1.adb shell dumpsys meminfo yourpakagename
Pss對應的TOTAL值:記憶體所實際佔用的值。
Dalvik Heap Size:從RuntimetotalMemory()獲得,DalvikHeap總共的記憶體大小。
Dalvik HeapAlloc:RuntimetotalMemory()-freeMemory() ,Dalvik Heap分配的記憶體大小。
Dalvik Heap Free:從RuntimefreeMemory()獲得,DalvikHeap剩餘的記憶體大小。
Dalvik Heap Size 約等於Dalvik HeapAlloc+ Dalvik HeapFree。
Cursor:/dev/ashmem/Cursor Cursor消耗的記憶體(KB)。
Ashmem:/dev/ashmem,匿名共享記憶體用來提供共享記憶體通過分配一個多個程序可以共享的帶名稱的記憶體塊。
Other dev:/dev/,內部driver佔用的在 “Otherdev”。
.so mmap:C 庫程式碼佔用的記憶體。
.jar mmap:Java 檔案程式碼佔用的記憶體。
.apk mmap:apk程式碼佔用的記憶體。
.ttf mmap:ttf 檔案程式碼佔用的記憶體。
.dex mmap:Dex 檔案程式碼佔用的記憶體。
Other mmap:其他檔案佔用的記憶體。
私有(Clean and Dirty)記憶體:
程序獨佔的記憶體。也就是應用程序銷燬時系統可以直接回收的記憶體容量。通常來說,“private dirty”記憶體是其最重要的部分,因為只被自己的程序使用。它只在記憶體中儲存,因此不能做分頁儲存到外存(Android不支援swap)。所有分配的Dalvik堆和本地堆都是“private dirty”記憶體;Dalvik堆和本地堆中和Zygote程序共享的部分是共享dirty記憶體。
實際使用記憶體 (PSS):
這是另一種應用記憶體使用的計算方式,把跨程序的共享頁也計算在內。任何獨佔的記憶體頁直接計算它的PSS值,而和其它程序共享的頁則按照共享的比例計算PSS值。例如,在兩個程序間共享的頁,計算進每個程序PPS的值是它的一半大小。PSS計算方式的一個好處是:把所有程序的PSS值加起來就可以確定所有程序總共佔用的記憶體。這意味著用PSS來計算程序的實際記憶體使用、程序間對比記憶體使用和總共剩餘記憶體大小是很好的方式。
通常來說,只需關心Pss Total列和Private Dirty列就可以了。在一些情況下,Private Clean列和Heap Alloc列也會提供很有用的資訊。下面是一些應該檢視的記憶體分配型別(行中列出的型別):
Dalvik Heap:
應用中Dalvik分配使用的記憶體。Pss Total包含所有的Zygote分配(如上面PSS定義所描述的,共享跨程序的加權)。Private Dirty是應用堆獨佔的記憶體大小,包含了獨自分配的部分和應用程序從Zygote複製分裂時被修改的Zygote分配的記憶體頁。注意:新平臺版本有Dalvik Other這一項。Dalvik Heap中的Pss Total和Private Dirty不包括Dalvik的開銷,例如即時編譯(JIT)和垃圾回收(GC),然而老版本都包含在Dalvik的開銷裡面。
Heap Alloc:
是應用中Dalvik堆和本地堆已經分配使用的大小。它的值比Pss Total和Private Dirty大,因為程序是從Zygote中複製分裂出來的,包含了程序共享的分配部分。
.so mmap和.dex mmap:
mmap對映的.so(本地) 和.dex(Dalvik)程式碼使用的記憶體。Pss Total 包含了跨應用共享的平臺程式碼;Private Clean是應用獨享的程式碼。通常來說,實際對映的記憶體大小要大一點——這裡顯示的記憶體大小是執行了當前操作後應用使用的記憶體大小。然而,.so mmap 的private dirty比較大,這是由於在載入到最終地址時已經為原生代碼分配好了記憶體空間。
Unknown:
無法歸類到其它項的記憶體頁。目前,這主要包含大部分的本地分配,就是那些在工具收集資料時由於地址空間佈局隨機化(Address Space Layout Randomization ,ASLR)不能被計算在內的部分。和Dalvik堆一樣, Unknown中的Pss Total把和Zygote共享的部分計算在內,Unknown中的Private Dirty只計算應用獨自使用的記憶體。
TOTAL:
程序總使用的實際使用記憶體(PSS),是上面所有PSS項的總和。它表明了程序總的記憶體使用量,可以直接用來和其它程序或總的可以記憶體進行比較。Private Dirty和Private Clean是程序獨自佔用的總記憶體,不會和其它程序共享。當程序銷燬時,它們(特別是Private Dirty)佔用的記憶體會重新釋放回系統。Dirty記憶體是已經被修改的記憶體頁,因此必須常駐記憶體(因為沒有swap);Clean記憶體是已經對映持久檔案使用的記憶體頁(例如正在被執行的程式碼),因此一段時間不使用的話就可以置換出去。
ViewRootImpl:
程序中活動的根檢視的數量。每個根檢視與一個視窗關聯,因此可以幫助確定涉及對話方塊和視窗的記憶體洩露。
AppContexts和Activities:
當前駐留在程序中的Context和Activity物件的數量。可以很快的確認常見的由於靜態引用而不能被垃圾回收的洩露的 Activity物件。這些物件通常有很多其它相關聯的分配,因此這是追查大的記憶體洩露的很好辦法。
小結:
1)Pss/SharedDirty/Private Dirty三列是讀取了/proc/process-id/smaps檔案獲取的,可以通過adbshell cat /proc/process-id/smaps來檢視(需要root)。這是個普通的linux檔案,描述了程序的虛擬記憶體區域(vm area)的具體資訊。每次mmap一般都會生成一個vm area
。它會對每個虛擬記憶體塊進行解析,然後生成資料。
2)Native HeapSize/Alloc/Free三列是使用C函式mallinfo得到的。為什麼有free的?或許可以理解為無論是c的malloc還是java的new,最後都是通過mmap系統呼叫進行記憶體分配的。而mmap必須以頁的4K為單位。所以如果一次一次只需要malloc 2K,則剩下的2K是free的。如果下次再malloc 2K,可以仍然使用上次mmap剩餘的2K記憶體。
3)Dalvik HeapSize/Alloc/Free並非該cpp檔案產生,而是android的Debug類生成。
2.adb shell procrank
PID Vss Rss Pss Uss cmdline
...... 2319 42068K 42032K 13536K 7028K com.xxx ......
- 一般來說記憶體佔用大小有如下規律:VSS >= RSS >= PSS >= USS
VSS - Virtual Set Size 虛擬耗用記憶體(包含共享庫佔用的記憶體)是單個程序全部可訪問的地址空間。
RSS - Resident Set Size 實際使用實體記憶體(包含共享庫佔用的記憶體)是單個程序實際佔用的記憶體大小,對於單個共享庫,儘管無論多少個程序使用,實際該共享庫只會被裝入記憶體一次。
PSS - Proportional Set Size 實際使用的實體記憶體(比例分配共享庫佔用的記憶體)。
USS - Unique Set Size 程序獨自佔用的實體記憶體(不包含共享庫佔用的記憶體)USS 是一個非常非常有用的數字,因為它揭示了執行一個特定程序的真實的記憶體增量大小。如果程序被終止, USS 就是實際被返還給系統的記憶體大小。USS 是針對某個程序開始有可疑記憶體洩露的情況,進行檢測的最佳數字。懷疑某個程式有記憶體洩露可以檢視這個值是否一直有增加。
- PID是程序ID。 Vss是佔用的虛擬記憶體,如果沒有對映實際的記憶體也算進來。 Rss是佔用的實體記憶體。是共享記憶體+私有記憶體。因為共享記憶體是多個程序共用的,所以存在重複計算。 Pss是佔用的私有記憶體加上平分的共享記憶體。例如一塊1M的共享記憶體被兩個程序共享,那每個程序分500K。各程序的Pss相加基本等於實際被使用的實體記憶體,所以這個經常是最重要的引數。 Uss是私有記憶體。 cmdline可以看做是apk包名。
- 對於procrank我們主要參考Uss列,dumpsys info我們看priv dirty。
- RSS: "Resident Set Size", 實際駐留"在記憶體中"的記憶體數. 不包括已經交換出去的程式碼. 舉一個例子: 如果你有一個程式使用了100K記憶體, 作業系統交換出40K記憶體, 那麼RSS為60K. RSS還包括了與其它程序共享的記憶體區域. 這些區域通常用於libc庫等.
- SHARE: RSS中與其它程序共享的記憶體部分大小.
- Private RSS: 對映到記憶體中的頁面, 這些頁面僅由程序單獨使用. 這也是我們最關心地方: 程序實際佔用的記憶體數(按:大概是RSS中不與其它程序共享的記憶體部分大小).
3.ps | grep appName直接輸出appName程序對應的記憶體資訊
4.adb shell dumpsys procstats --hours 3
也可在4.4版本的手機中點選Settings > Developer options > ProcessStats,如下圖:
5.adb shell showmap
該命令輸出的每行表示一個vm area,列出了該vm area的start addr, end addr, Vss, Rss, Pss, shared clean, shareddirty, private clean, private dirty,object。 startaddr和end addr表示程序空間的起止虛擬地址。
Object:可以看做mmap的檔名。
Shared clean:按字面意思,表示共享的乾淨的資料。共享表示多個程序的虛擬地址可以都指向這塊物理空間,表示多個程序共享的so庫。為什麼這裡說是多個程序共享的so而不是所有的so呢?關於so庫的載入,有可能是mmap帶MAP_SHARED引數,但看了memory_faq,才知道是MAP_PRIVATE。如果使用showmap命令檢視vm area,會發現有的so的記憶體都屬於Sharedclean,而有的so則屬於private clean。前者一般是當前程序特有的so,而後者一般是通用的so。後來看了對mmap的各種引數的實驗(很贊實踐精神),才知道第一次以MAP_PRIVATE mmap so,記憶體都是private clean的。如果另外一個程序mmap了同一個so,那該vm area就變成shared clean了。
Private clean:包括該程序私有的乾淨的記憶體。包括前面說的該程序獨自使用的so和程序的二進位制程式碼段。Clean記憶體的好處是在記憶體緊張時,可以釋放實體記憶體。因為是clean的,所以不需要寫回到disk,只需要下次讀取該記憶體(導致缺頁錯誤)時再從disk讀入。
Private dirty:非共享,又不能被換頁出去的記憶體(比如linux系統中為了提高分配記憶體速度而緩衝的小物件,即使你的程序已經退出,該記憶體也不會被釋放)。表示該程序私有的不跟disk資料一致的記憶體段。例如堆(heap),棧(stack),bss段。關於bss段,因為在elf檔案為了節約控制元件沒有賦值,所以在載入到記憶體時賦值為0,於是跟disk就不一致了。在showmap結果中,會發現幾乎每個so都有一個顯示位[bss]的private dirty段。資料段我估計是private clean的,因為elf檔案是有初值的。
Shared dirty:共享,但又不能被換頁出去的記憶體。看了Dalvikvm internal這個video(slides),才明白了些。對於普通的linux程序,當父程序fork子程序時,父程序的虛擬記憶體區域都會”複製“一份到子程序中。這裡”複製“加引號,是因為為了節省記憶體,也為了減少記憶體拷貝的時間,使用的是copy-on-write的方法。當子程序對private dirty的堆,棧,bss沒有修改時,則是父子程序share這份dirty(因為跟disk沒法對映)資料。如果發生改變,則會修改為private dirty。所以android有zygote程序,是所有android apps程序的父程序,在其中會載入resource等資源(下文會看到,最簡單的應該也有大概5M resource,例如圖片),這些資源都是隻讀的。具體的apps繼承了這些shared dirty的資料,因為不修改它們,所以也不用分配多餘的記憶體空間。由於android使用的linux沒有swap分割槽,所以dirty的資料必須常駐記憶體。所以dumpsys meminfo會把private dirty和shared dirty重點列出來,這也是我們優化記憶體的重點。
Android程式記憶體被分為2部分:native和dalvik,dalvik就是我們平常說的java堆,我們建立的物件是在這裡面分配的,而bitmap是直接在native上分配的,對於記憶體的限制是 native+dalvik 不能超過最大限制。Android程式記憶體一般限制在16M,當然也有24M的。
為什麼NativeHeap(根據mallinfo系統呼叫得到)很大而Native Pss(根據swaps得到)很小?可能是dumpsys meminfo的一個bug。根據android_os_Debug.cpp的程式碼,object名字是[heap]的段被認為是native heap。這在2.3是正確的,但在4.0之後,[heap]為名字的段卻很小(只有幾K)。同時,有大量的[anon]的區域。anon可能是anonymous的縮寫。malloc一般是通過mmap來分配記憶體的,而引數是MAP_ANONYMOUS。所以這些[anon]是native heap。從大小上看,現在這些[anon]被看做是Unkown的一部分,也跟hative heap的大小差不多。
6.adb shell cat /proc/meminfo 即可在命令列裡顯示meminfo檔案的內容,具體如下所示:
MemTotal: 所有可用記憶體大小。
MemFree: LowFree與HighFree的總和,被系統留著未使用的記憶體。
Buffers: 用來給檔案做緩衝大小。
Cached: 被高速緩衝儲存器(cache memory)用的記憶體的大小(等於diskcache minus SwapCache)。
SwapCached:被高速緩衝儲存器(cache memory)用的交換空間的大小。已經被交換出來的記憶體,仍然被存放在swapfile中,用來在需要的時候很快的被替換而不需要再次開啟I/O埠。
Active: 在活躍使用中的緩衝或高速緩衝儲存器頁面檔案的大小,除非非常必要,否則不會被移作他用。
Inactive: 在不經常使用中的緩衝或高速緩衝儲存器頁面檔案的大小,可能被用於其他途徑。
SwapTotal: 交換空間的總大小。
SwapFree: 未被使用交換空間的大小。
Dirty: 等待被寫回到磁碟的記憶體大小。
Writeback: 正在被寫回到磁碟的記憶體大小。
AnonPages:未對映頁的記憶體大小。
Mapped: 裝置和檔案等對映的大小。
Slab: 核心資料結構快取的大小,可以減少申請和釋放記憶體帶來的消耗。
SReclaimable:可收回Slab的大小。
SUnreclaim:不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)。
PageTables:管理記憶體分頁頁面的索引表的大小。
NFS_Unstable:不穩定頁表的大小。
同理,讀取"/proc/cupinfo"可以獲取android手機的CPU引數,"/proc/stat"檔案可以計算CPU的使用率.
相關推薦
Android記憶體分析工具(四):adb命令
1.adb shell dumpsys meminfo yourpakagename Pss對應的TOTAL值:記憶體所實際佔用的值。 Dalvik Heap Size:從RuntimetotalMemory()獲得,DalvikHeap總共的記憶體大小。 Dalvik
centos7搭建ELK Cluster集群日誌分析平臺(四):簡單測試
-1 簡單測試 logs ima .tar.gz 分析 -c cluster images 續之前安裝好的ELK集群 各主機:es-1 ~ es-3 :192.168.1.21/22/23 logstash: 192.168.1.24 ki
Android項目實戰(四):ViewPager切換動畫(3.0版本以上有效果)
技術 code info utf-8 play draw pos support addview 原文:Android項目實戰(四):ViewPager切換動畫(3.0版本以上有效果)學習內容來自“慕課網” 一般APP進去之後都會有幾張圖片來導航,
Android ANR分析實踐(一):北京×××搭建ANR是什麽、產生的原因及如何避免ANR
例如 三種 handler 線程處理 不足 線程阻塞 種類 工具 input 一、 什麽是北京×××搭建 dsluntan.com VX:17061863513ANR ANR,(Application Not Responding) 即應用程序無響應,在android應
gulp前端自動化構建工具(四):gulp檔案路徑處理模組
本篇前言 上一篇介紹了本工具的獨立配置檔案,歡迎閱讀 本篇還是先把gulpfile.js執行所用的一個方法模組展示出來,模組主要接收gulp.src()中檔案物件,對檔案自身所在的物理路徑及其內部資源引用的路徑進行處理,程式碼中我有做詳細的註釋,包括方法的單獨作用演示。 本
Android效能分析工具(二)
DDMS DDMS 的全稱是Dalvik Debug Monitor Service,是Android 開發環境中的Dalvik 虛擬機器除錯監控服務 HierarchyViewer UI效能分析工具,分析佈局檔案的效能,層級巢狀 UI佈局複雜程度及冗餘分析,View巢狀的冗餘層級 View的效能指標
Android Bluetooth Stack: Bluedroid(四):Scan remote devices
Enable Bluetooth之後就可以掃描周圍的其他discoverable mode的Bluetooth Device。以下簡單分析以下Bluetooth BR/EDR裝置的掃描過程,然後會談一下Android 4.2引入的Bluetooth HAL。
SQL基礎(四):SQL命令
版本 數據庫應用 ges odi 改變 sql per 測試 數據類型 1、CREATE INDEX 語句 CREATE INDEX 語句用於在表中創建索引。在不讀取整個表的情況下,索引使數據庫應用程序可以更快地查找數據。 索引:在表中創建索引,以便更加快速高效地查
linux系列(四):mkdir命令
1、命令格式: mkdir [選項] 目錄名 2、命令功能: 通過 mkdir 命令可以實現在指定位置建立以 DirName(指定的檔名)命名的資料夾或目錄。要建立資料夾或目錄的使用者必須對所建立的資料夾的父資料夾具有寫許可權。並且,所建立的資料夾(目錄)
webRTC中音訊相關的netEQ(五):DSP處理 webRTC中音訊相關的netEQ(四):控制命令決策 webRTC中音訊相關的netEQ(二):資料結構)
上篇(webRTC中音訊相關的netEQ(四):控制命令決策)講了MCU模組是怎麼根據網路延時、抖動緩衝延時和反饋報告等來決定給DSP模組發什麼控制命令的。DSP模組根據收到的命令進行相關處理,處理簡要流程圖如下。 從上圖看出如果有語音包從packet buffer裡取出來先要做解碼得到PC
webRTC中音訊相關的netEQ(四):控制命令決策
上篇(webRTC中音訊相關的netEQ(三):存取包和延時計算)講了語音包的存取以及網路延時和抖動緩衝延時的計算,MCU也收到了DSP模組發來的反饋報告。本文講MCU模組如何根據網路延時、抖動緩衝延時和反饋報告等決定發給DSP模組的控制命令, 好讓DSP模組先對取出的語音包做解碼處理(如果有的話)以及根據這
android記憶體分析工具- MAT的初識(1)
目標:該系列文章帶領大家掌握android記憶體溢位的排查,讓記憶體問題不再是android開發者的門檻。 DDMS(Dalvik Debug Monitor Server)和MAT(Memory Analyzer Tool)這兩個工具可以很好地幫助我們分析優
WebRTC-Android 原始碼導讀(四):VideoCRE 與記憶體抖動優化
前面三篇中,我們依次分析了 WebRTC Android 的視訊採集、視訊渲染和視訊硬編碼,Live Streaming 視訊的前段就已經全了。WebRTC 是個寶,初窺這部分程式碼時就被它的 Capturer 類的設計驚豔到了,仔細品鑑後越發佩服起來,裡面簡直填了太多坑了,
xv6原始碼分析(四):記憶體管理
xv6通過頁表機制實現了對記憶體空間的控制。頁表使得 xv6 能夠讓不同程序各自的地址空間對映到相同的實體記憶體上,還能夠為不同程序的記憶體提供保護。 除此之外,我們還能夠通過使用頁表來間接地實現一些特殊功能。xv6 主要利用頁表來區分多個地址空間,保護記憶體。
並發編程(四):ThreadLocal從源碼分析總結到內存泄漏
ngs 一個 交互 而且 當前 logs 點雲 然而 垃圾 一、目錄 1、ThreadLocal是什麽?有什麽用? 2、ThreadLocal源碼簡要總結? 3、ThreadLocal為什麽會導致內存泄漏? 二、ThreadLocal是
Java併發(四):volatile的實現原理 Java併發(一):Java記憶體模型乾貨總結
synchronized是一個重量級的鎖,volatile通常被比喻成輕量級的synchronized volatile是一個變數修飾符,只能用來修飾變數。 volatile寫:當寫一個volatile變數時,JMM會把該執行緒對應的本地記憶體中的共享變數重新整理到主記憶體。 volatile讀:當讀一
【Android開發—智慧家居系列】(四):UDP通訊傳送指令
【Android開發—智慧家居系列】(四):UDP通訊傳送指令 思路回顧 【1】手機連線WIFI模組 【2】UDP通訊對WIFI模組傳送指令,以和WIFI模組保持連線狀態 【3】UDP通訊對WIFI模組傳送指令,讓其搜尋可用的無線網,返回WIFI列表
Eclipse MAT記憶體分析工具(Memory Analyzer Tool)
MAT記憶體分析工具 MAT是Memory Analyzer的簡稱,它是一款功能強大的Java堆記憶體分析器。可以用於查詢記憶體洩露以及檢視記憶體消耗情況。MAT是基於Eclipse開發的,是一款免費的效能分析工具。讀者可以在http://www.eclipse.org/mat/下載並使用MAT。 1 初
Caffe原始碼(四):math_functions 分析
轉自:https://blog.csdn.net/seven_first/article/details/47378697#1-caffecpugemm-%E5%87%BD%E6%95%B0 主要函式 math_function 定義了caffe 中用到的一些矩陣操作和數值計算的一些函式,這
SpringBoot2.0原始碼分析(四):spring-data-jpa分析
SpringBoot具體整合rabbitMQ可參考:SpringBoot2.0應用(四):SpringBoot2.0之spring-data-jpa JpaRepositories自動注入 當專案中存在org.springframework.data.jpa.repository.JpaRepositor