Android性能優化典范 - 第1季 閱讀筆記

該文章是自己在閱讀 Android性能優化典范-第一季 時的讀書筆記,Android性能優化典范主要講了Android的渲染機制、內存和GC以及電量優化方面相關的內容,因為內容比較龐雜,加上一些知識點需要花心思去理解,所以在閱讀的時候,順便記錄一下自己的閱讀理解。

原文 Android性能優化典范-第一季

筆記條目

1、Android 系統每隔 16ms 發出 VSYNC 信號,觸發硬件對 UI 的渲染。

2、1秒 = 1000ms 所以基于上面的規則,每一秒 UI 應該渲染 1000/16 = 60 (次),也就是我們經常看到的 60hz 這個值,表示一秒內刷新屏幕的次數,用術語講 這叫刷新率(Refresh Rate)。

3、刷新率這個值取決于硬件的固定參數,一般的這個值為60fps,原因在于人眼與大腦無法感知超過60fps的界面更新。

4、幀率是區別于刷新率的另一個概念,他代表每一秒GPU繪制操作的幀數

Note :兩者的區別在于刷新率表示屏幕會按照這個頻率去不停的刷新屏幕,至于屏幕上顯示什么他控制不了,幀率表示GPU(圖形處理器)一秒內繪制的次數,他倆前者負責按刷新率不停刷新界面,后者負責按幀率去不停繪制界面。

5、刷新率和幀率需要結合在一起工作,才能讓視圖內容呈現在屏幕。

6、GPU獲取圖形數據并繪制,硬件負責把GPU生成的視圖數據拿出來顯示在屏幕上,這個過程一遍遍的在我們的手機中發生著。

如果屏幕刷新率和GPU幀率一致,那肯定是極好的,GPU每隔特定時間準備好視圖數據。然后相應的 ,因為屏幕刷新率跟幀率一致,所以,此時此刻屏幕正好也刷新界面,視圖正常顯示。

但是大多數情況下,他倆的步調可能不一致,所以會出現錯位的情況

此時,GPU 那邊準備了數據,但是屏幕這邊缺不能及時的顯示出來。

7、界面渲染雙緩沖技術

一般我們在繪制UI的時候,都會采用一種稱為“雙緩沖”的技術。雙緩沖意味著要使用兩個緩沖區(SharedBufferStack中),其中一個稱為Front Buffer,另外一個稱為Back Buffer。UI總是先在Back Buffer中繪制,然后再和Front Buffer交換,渲染到顯示設備中。理想情況下,這樣一個刷新會在16ms內完成(60FPS)

更多詳情可參考 http://djt.qq.com/article/view/987?ADTAG=email.InnerAD.weekly.20131216

8、任何時候,只要 View 中的繪制內容發生變化,都會重新執行創建 DisplayList 、渲染 DisplayList

9、Android 中的內存模型分三級(這里的內存應該指的是堆內存)分別為 Young Generation、Old Generation、Permanent(常駐) Generation,也就是說 Android 虛擬機中的堆內存假如有125M,那么這125M會被指定為不同的類型,具體怎么指定,不用細究,他可以對每一塊區域設置一個變量,用于指示這個區域是屬于哪一級,這個純屬個人臆想,但說這么多,就是為了說明一個事實,Android 堆內存 那塊空間會被劃分為三種不同的類型,Young、Old、Permanent。

這里每個區域肯定一個具體的大小值,具體大小的分配就是 JVM 的事了, Old 區、Permanent 區的大小要大于 Young 區。

10、對內存區域分級的意義,先不看官方介紹,個人推測一下也不難知道,這樣做就是為了更好的利用內存空間這么如此寶貴的地方。被劃分成不同的區域后,我們每次 new 一個新對象時,毫無疑問,新對象分配的空間應該在 Young Genration 內存區域內。

11、該說說垃圾回收了。當我們的程序不斷的運行、不斷的創建對象,Young 區的空間肯定有被用完的時候,此時 JVM 檢測到 內存空間不夠用,就會啟動 GC ,執行垃圾回收,此時他很可能會對 Young 區的一些值做一些判斷,看他們是不是被頻繁的使用,如果是,他應該會把這部分內存空間標記為 Old。同樣的道理,Old 區的對象也可能被轉移到 Permanent 去,總之 JVM 這樣做就是為了提高對象創建的效率。

垃圾回收會把 Young 區中無用的對象給清理掉。

12、關于上述的推測,這里是胡凱博文中的原話,對照理解下:

Android里面是一個三級Generation的內存模型,最近分配的對象會存放在Young Generation區域,當這個對象在這個區域停留的時間達到一定程度,它會被移動到Old Generation,最后到Permanent Generation區域。

每一個級別的內存區域都有固定的大小,此后不斷有新的對象被分配到此區域,當這些對象總的大小快達到這一級別內存區域的閥值時,會觸發GC的操作,以便騰出空間來存放其他新的對象。

13、內存泄露問題。胡凱博文寫的很清楚明白,直接引用胡凱的原文

內存泄漏指的是那些程序不再使用的對象無法被GC識別,這樣就導致這個對象一直留在內存當中,占用了寶貴的內存空間。顯然,這還使得每級Generation的內存區域可用空間變小,GC就會更容易被觸發,從而引起性能問題。

內存泄露為什么會導致性能問題,上面的這段話很精辟的指出來了。就是因為泄露的對象會沉積在內存區,隨著泄露的對象越來越多,JVM 周期性的 GC 后發現內存空間依舊滿滿的,此時就會發生大家常說的內存溢出問題了。

其實垃圾回收器(GC)在很努力的回收內存區中的無用對象,但是每次掃描卻發現 那些泄露的對象一直被一些或者的對象所持有,所以內存泄露問題,一定在開發中需要重視。

14、每次 GC 的時候,其他所有線程都是暫停狀態,也就是說 GC操作會暫停其他任務。

開發 Tip

以上是自己在閱讀《Android性能優化典范》時的筆記,感謝作者可以把視頻內容轉化為更加容易理解的文章。 但是任何好文章,閱讀完應該可以給讀者一些指導,這篇文章中講了很多概念以及原理,下面就針對文章,總結一些開發過程中應該遵循的一些建議,以期讓自己的 App 具有更好的性能。

1、避免在 for 循環中給對象分配內存,直白一點就是說 不要在 for 循環中 new 對象,最好可以移動到 for 之前。

2、避免在自定義 View 時,在 onDraw 方法中執行太復雜的邏輯操作。

3、避免在 onDraw 方法中 創建對象,因為在界面繪制時,該方法可能會被大量的重復執行,這樣會導致一瞬間產生大量的對象,從而導致堆空間中瞬間產生大量無用對象,從而觸發 JVM 的 GC 操作。

Note :一些情況下,無法避免在 onDraw 方法中創建對象,那么此時為了優化性能,可以采取對象池的策略,手動緩存已創建的對象,并加以復用,從而降低性能損失。但是使用此方法,需要注意一點,應該及時的手動清理對象池,否則可能會引起更加嚴重的內存問題。

4、開發app的性能目標就是保持60fps,這意味著每一幀你只有16ms=1000/60的時間來處理所有的任務。所以我們的布局能簡單則簡單。

5、考慮到過渡繪制,我們在寫布局 layout 時,不應該隨意的去為一些 View 設置 background,例如,當我們的根布局已經設置過一次背景色,那么子view默認的背景色就是它了,所以對于一些子 View ,如果它跟根布局背景顏色一致,那么該 View 就無需再設置背景色了,另外一些情況可能需要設置 selector,此時默認背景可以設置為 透明色。

6、對于電量優化,我們應該減少喚醒屏幕的次數以及持續時間,使用 WeakLock 處理喚醒問題。

7、對一些非必須馬上執行的操作,可以等待手機處于充電狀態或者電量充足時再執行。

8、對一些零散的網絡請求,可以打包一次操作,避免過多的無線信號引起的電量消耗。

來自: http://gudong.name/note/2016/01/13/android-performance-patterns-first-note.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!