Android Monitor
Android Studio 內置了四種性能監測工具Memory Monitor、Network Monitor、CPU Monitor、GPU Monitor,我們可以使用這些工具監測APP的狀態,該文簡單介紹下這些工具的使用
Memory Monitor
Memory Monitor工具主要是用來監測APP的內存分配情況,判斷是否存在內存泄漏。連接設備,選擇好要監測的APP,如圖所示:
A:手動觸發GC操作
B:獲取當前的堆棧信息,生成.hprof文件
C:內存分配追蹤工具,生成.alloc文件
D:已使用內存
E:剩余可用內存
通過與應用交互并在Memory Monitor中觀察它是如何影響內存的使用,圖表可以為你展示一些潛在的問題:
1.頻繁的垃圾收集活動使應用運行緩慢。
2.應用耗盡內存導致app崩潰.
3.潛在的內存泄漏
正常情況下,上圖中的D區域會隨著時間的走勢慢慢上升(就算你與APP沒有任何交互),直到E區域被用完,則會觸發GC操作,釋放內存,周而復始。如果你發現你的應用是靜態的,但是E區域的內存很快就被用完了,即頻繁的觸發GC操作,這時你就應該引起重視,說不定你的代碼中就存在著引起內存泄漏的隱患。
Dump Java Heap
使用場景:定位內存泄漏
點擊上圖中的B按鈕開始檢測APP,此時APP會變得很卡,容易發生ANR,一段時間過后會生成.hprof文件,如下圖所示
這里的截圖是我故意生成的一個能引起內存泄漏的例子,點擊上圖右上方的Analyzer Tasks按鈕,若代碼中存在內存泄漏隱患,在其下方會列出可能引起內存泄漏的Activity,如上圖右下方的Leaked Activities,之后我們便可以結合左下方Reference Tree中指出的問題分析,如果你有源碼的話還可以索引源碼(右鍵->Jump to source)。實例代碼如下:
多次旋轉屏幕,使得內存不斷增加就容易引起內存泄漏。
上面的例子比較簡單,可以直接通過Memory Monitor工具就能直接看出,在平常的開發中內存泄漏的問題往往沒有這么簡單,我們可以借助MAT工具分析。
MAT
MAT(Memory Analyzer Tool) ,一個基于Eclipse的內存分析工具,是一個快速、功能豐富的JAVA heap分析工具,它可以幫助我們查找內存泄漏和減少內存消耗。使用內存分析工具從眾多的對象中進行分析,快速的計算出在內存中對象的占用大小,看看是誰阻止了垃圾收集器的回收工作,并可以通過報表直觀的查看到可能造成這種結果的對象。
在使用MAT工具前,我們需要將.hprof文件轉換成標準的.hprof文件才能被識別,在Android Studio中可以通過以下操作轉換
之后用MAT打開,顯示如下
點擊Histogram按鈕
如圖所示,該圖會列出內存中所有的對象的個數即其占用的內存大小,其次,我們可以輸入指定的Activity名稱來縮小定位范圍
如圖所示,這里列出了MainActivity和其內部類MyThread的對象個數即占用的內存大小,接下來我們選擇一個條目右鍵—>Merge Shortest Paths to GC Roots(查看一個對象到GC Roots是否存在引用鏈相連接)->Merge Shortest Paths to GC Roots(排除虛引用/弱引用/軟引用等等),
如上圖所示,就是可能存在內存泄漏的地方,具體還是要結合代碼分析。
GC Roots
對象存活的判定:
當一個對象不會再被使用的時候,我們會說這對象已經死亡。對象何時死亡,寫程序的人應當是最清楚的。如果計算機也要弄清楚這件事情,就需要使用一些方法來進行對象存活判定,常見的方法有 引用計數(Reference Counting) 和 有可達性分析(Reachability Analysis) 兩種。
引用計數算法的大致思想是給對象中添加一個引用計數器,每當有一個地方引用它時,計數器值就加1;當引用失效時,計數器值就減1;任何時刻計數器為0的對象就是不可能再被使用的。
Java語言里面沒有選用引用計數算法來管理內存,其中最主要原因是它沒有一個優雅的方案解決對象之間相互循環引用的問題:
當兩個對象互相引用,即使它們都無法被外界使用時,它們的引用計數器也不會為0。
可達性算法的基本思路就是通過一系列的稱為GC根節點(GC Roots)的對象作為起始點,從這些節點開始進行向下搜索,搜索所走過的路徑成為引用鏈(Reference Chain),當一個對象到GC Roots沒有任何引用鏈相連(用圖論的話來說就是從GC Roots到這個對象不可達)時,則證明此對象是不可用的。
如上圖,對象object 5、object 6、object 7雖然互相有關聯,它們的引用并不為0,但是它們到GC Roots是不可達的,因此它們將會被判定為是可回收的對象。
Allocation Tracker
在內存圖中點擊C,啟動追蹤,再次點擊停止追蹤,隨后自動生成一個alloc結尾的文件,這個文件就記錄了這次追蹤到的所有數據。
如上圖,我們可以看出這次操作中應用里的各個組件的分配次數與占用大小,若發現這兩個數據有異常(分配過多,占用過大),同樣可以索引源碼優化(前提是你有),最下方的視圖是以另一種較酷炫的方式呈現,感興趣的可以具體結合文件操作。
Network Monitor
Network Monitor是用于顯示app網絡請求的狀態,頻繁的網絡請求是耗電的重要原因
如上圖所示,Tx與Rx分別表示上下行的速度。
GPU Monitor
GPU Monitor工具可以將進行UI渲染工作所花的時間表現出來,它記錄下渲染線程準備以及進行描繪的時間。
Android系統每隔16ms發出VSYNC信號,觸發對UI進行渲染,如果每次渲染都成功,這樣就能夠達到流暢的畫面所需要的60fps,為了能夠實現60fps,這意味著程序的大多數操作都必須在16ms內完成。
Why 60fps?
我們通常都會提到60fps與16ms,可是知道為何會是以程序是否達到60fps來作為App性能的衡量標準嗎?這是因為人眼與大腦之間的協作無法感知超過60fps的畫面更新。
12fps大概類似手動快速翻動書籍的幀率,這明顯是可以感知到不夠順滑的。24fps使得人眼感知的是連續線性的運動,這其實是歸功于運動模糊的效果。24fps是電影膠圈通常使用的幀率,因為這個幀率已經足夠支撐大部分電影畫面需要表達的內容,同時能夠最大的減少費用支出。但是低于30fps是無法順暢表現絢麗的畫面內容的,此時就需要用到60fps來達到想要的效果,當然超過60fps是沒有必要的。
開發app的性能目標就是保持60fps,這意味著每一幀你只有16ms=1000/60的時間來處理所有的任務。
Get GPU Trace
如上圖所示,就是GPU Monitor的樣子,點擊上圖獲取gfxtrace按鈕后,出現彈出框讓你選擇要監測的指定線程
選定后點擊Trace
過程中會加載指定的lib,同時手機會彈出Dialog
環境需滿足條件(手機root,安裝GPU Debugging tools以及相關lib),若不滿足會提示:“Failed to connect to the graphics debugger”,假設這里已滿足條件
判斷是否在獲取trace的依據是隨著你的操作,上圖的值不斷增長,點擊stop獲得這個過程中生成的gfxtrace。
GPU Debugger
GPU Debuger是檢查OpenGL ES 2.0或3.1渲染app圖形的情況,打開之前生成的gfxtrace
渲染上下文:
渲染上下文是執行OpenGL ES命令所需的。它用來收集渲染一張圖片所需的狀態,包括相關的緩存區、陰影、紋理等。許多游戲應用程序只有一個上下文。更高級的應用程序可以使用超過一個上下文。
如果你選擇了一個上下文,在GPU Commands 面板中的調用方法將按照調用順序排列。
渲染時間線:
渲染時間線中的縮略圖和GPU Commands 面板下的Frame一一對應,GPU Commands 面板顯示了 OpenGL ES 生成每一幀的調用層級。
支持雙buffer的apps渲染一幀的結尾函數是eglSwapBuffers()方法。
Framebuffer Pane
在GPU Commands面板中選擇一幀(生成這一個由多個Draw函數完成,在Draw函數中又有多個openGL ES方法),Framebuffer 面板顯示的內容取決于最后一個方法。
對于上圖紅框中各項工具的具體作用可以查看 官網 的描述,本地測試的時候作用不夠明顯。
Textures Pane
Geometry pane
幾何面板的介紹同樣本地的操作不夠直觀,可以直接查看 官網 介紹
GPU state pane
查看當前GPU的狀態
Memory pane
查看所選方法的值在內存中的保存情況
CPU Monitor
CPU Monitor可以對代碼中的方法進行檢測,同樣可以生成一個Trace文件
生成的Trace文件如下圖
通過方法的調用次數和所花時間來查看,通常判斷方法是:
1.如果方法調用次數不多,但每次調用卻需要花費很長的時間的函數,可能會有問題。
2.如果自身占用時間不長,但調用卻非常頻繁的函數也可能會有問題。
來自:http://rkhcy.github.io/2017/02/14/Android Monitor/