標籤:info 片段 變更 細節 初始化 space target run 最大
Dalvik :http://zh.wikipedia.org/wiki/Dalvik%E8%99%9A%E6%8B%9F%E6%9C%BA
ART :http://source.android.com/devices/tech/dalvik/art.html
本文
Ian Rogers 在Google IO 2014上講述了 The ART runtime 的Garbage Collection部分,通過他的講述,我們可以瞭解到ART在記憶體回收方面有哪些改進的地方。開門見山,下面我們就來瞭解一下具體的細節:
首先來看一下GC在Dalvik裡是如何工作的:
圖1 : GC的過程
圖2 :掛起所有線程進行標記,記憶體回收以釋放空間
從圖1可以看到當Dalvik開始記憶體回收時,GC會去尋找所有活動的對象,這個時候整個程式的線程就會掛起,並且虛擬機器內部的所有線程也會同時掛起(圖2) ,這樣目的是在較少的堆棧裡找到所引用的對象。需要注意的是這個回收動作是和應用程式同時執行。
這裡之所以要掛起所有線程是確保所有程式沒有進行任何變更,與此同時GC會隱藏所有處理過的對象,最終,確保標記了所有需要回收的對象後,GC才會恢複所有線程,並釋放空間。
因此在Dalvik裡,掛起所有線程這個動作的優先順序非常高,在記憶體緊張的時候就會頻繁執行這個動作,這樣就會造成丟幀,介面卡頓的現象。
圖3 : 為什麼Dalvik 裡的GC這麼挫?
從圖3可以看到,當發現需要給一個較大的對象(藍色方塊)分配空間時,發現可用空間還是夠的,但沒有這麼大的連續空間供新對象使用,這個時候就不得不進行一次GC回收(紅色方塊)(圖3),為大對象騰出較大並且連續的空間。這就是我們在分配一個較大對象的時候非常容易引起丟幀和卡頓的原因之一。解決方案可以是:把較大對象分解成幾個較小的對象再進行初始化,但這解決不了根本問題。
我們還可以用一個現實中比較形象的小區停車現象來闡釋:一輛較長的汽車A(藍色方塊)來找車位,發現空的位置很多,但車與車之間的間距較大,沒有適合A汽車停的位置,這個時候就不得不讓車位管理員M(GC)去尋找確認是否有非本小區的車輛(紅色方塊)並回收車位,供A汽車使用。(這裡我們可以發現,如果車停得夠緊湊,就無需麻煩車位管理員)
通過上面3張圖我們可以看到Dalvik中GC的問題如下:
1. GC時掛起所有線程
2. 大而連續的空間緊張
3. 記憶體片段化嚴重
下面我們來瞭解一下ART是如何解決這些問題的:
圖4 在ART中不需要掛起所有程式的線程
這裡可以對比著圖1一起看,在ART中GC會要求程式在分配空間的時候標記自身的堆棧,這個過程非常短,不需要掛起所有程式的線程.這樣就節約了很大一部分時間去尋找使用中的物件。(解決問題1)
圖5 提供 LOS :large object space 專供Bitmap使用
從圖5可以看到,ART裡會有一個獨立的LOS供Bitmap使用,從而提高了GC的管理效率和整體效能。
同樣我們從小區停車現象理解:小區裡划出了一塊大車專用的地區,使得大車省去了找車位的時間,也減少了通知管理員M(GC)的次數。(解決問題2)
圖6 ART中的 moving collector
在ART裡還會有一個moving collector來壓縮使用中的物件(綠色方塊),使得記憶體空間更加緊湊。
從小區停車現象理解:車位管理員M會定期移動停得不規範的車,使得停車空間更加緊湊,最大化利用有效空間。(解決問題3)
在解決了以上三個問題之後,ART就具備了以下優點:
1.更少的記憶體片段
2.更短更少的中斷和阻塞
3.更低的記憶體使用量率
總結 :Google在ART裡對GC做了非常大的最佳化,從示範的資料裡看,記憶體配置的效率提高了10倍,GC的效率提高了2-3倍。主要是通過標記時機的變更使中斷和阻塞的時間更短;通過LOS解決大對象的記憶體配置和儲存問題;通過moving collector來壓縮記憶體,使記憶體空間更加緊湊,從而達到GC整體效能的巨大提升。
android虛擬機器的垃圾收集