Flutter中的垃圾回收機制

1.介紹

Flutter主要使用Dart開發語言,在調試和發佈兩個版本中,Dart RunTime是始終存在,但兩種版本下的構建方式有很大的差別java

2.調試和發佈版本下的差別

  • 調試版本下 Dart編譯到設備,包含三部分:ios

    1.Dart RunTime算法

    2.jit(Android下的實時編譯器)/interpreter(IOS下的解析器)瀏覽器

    3.調試和分析服務less

  • 發佈版本下jvm

    1.Dart RunTime性能

兩種模式下都存在Dart RunTime,它包含了垃圾收集器,是實例化對象並變得沒法訪問時分配和釋放內存的必要組件。優化

3.垃圾收集器競技場

對於Flutter而言,會建立不少對象:例如Stateless Widget從建立到應用程序的狀態發生改變或者變得再也不可見時被銷燬和重建,大多數對象的生命週期是短暫的,若應用程序的UI變得相對複雜,可運行至上千個小部件線程

對於上面而言,不少人以前認爲Flutter爲何不用Java寫,爲何不用Object-C寫,爲何不用JavaScript寫,對於這些語言真的能勝任這麼頻繁的建立銷燬嗎?指針

  • Java垃圾收集器

    • jvm中java的內存分爲四個部分:

      1.Java棧:主要做用存放方法執行的時候全部的數據,由棧幀表明一個方法的執行,每一個方法從調用到執行完成在虛擬機爲一個棧幀的入棧和出棧,棧幀的信息包括局部變量表,棧操做數,動態連接,方法出口

      2.本地方法棧:主要爲native服務,例如C、C++方法

      3.方法區:存儲被虛擬機加載的類信息、常量、靜態變量、即便編譯器編譯後的數據等

      4.堆區:全部經過new建立的對象的內存都在堆中分配,堆內存分爲新的和舊的,剛new出來的對象放在新生代存儲,當內存不足時,虛擬機會經過一系列算法把新生對象移動到舊生代中去

    • 注意:

      1.當方法棧深度大於JVM深度的時候,就會棧溢出,例如:死循環(stackOverflow)

      2.新生代和舊生代都滿了,就會致使內存溢出(OutOfMemory)

    • 垃圾收集器的算法

      垃圾回收主要針對堆內存,算法主要包括垃圾的肯定與收集、垃圾的回收、垃圾的回收時機

      1.引用計數法(廢棄):若對象被引用就會+1,沒有被引用的時候就回收,但引用計數法沒法解決對象之間相互調用的問題

      2.可達性算法:經過gc root對象開始搜索,不可達的對象會被回收,引用的類型主要有強引用、弱引用,當存在強引用時寧願拋出oom也不回收、可是弱引用的話,有可能被回收。

      3.標記清除法:搜索發現沒有引用的對象直接回收,可是致使碎片過多

      4.複製算法:搜索掃描沒有引用的對象,開闢新的內存空間,將存活的對象複製到新的內存,舊的內存直接刪除,因爲交換空間,適合對象比較少的時候,而且內存空間縮短一半

      5.標記整理法:在標記清除法的基礎上,清除掉不存活的對象,把後面存活的對象挪動過來,解決碎片問題

    • 上面的垃圾收集器算法在jvm中沒有明確的規範,由各個廠商去實現

  • Object-C垃圾收集器

OC在早期版本中缺乏較爲完善的內存管理機制,須要開發者手動進行釋放,在Xcode4.2以後引入了ARC(Automatic Reference Counting)機制。

  • ARC機制

    ARC叫作自動引用計數,ARC中常見的全部權關鍵字:

    • assign 對應關鍵字__unsafe_unretained,指向的對象被釋放的時候,仍然指向以前的地址,容易引發野指針
    • copy 對應關鍵字__strong,在賦值的時候,調用copy方法
    • retain 對應關鍵字__strong
    • strong 對應關鍵字__strong
    • unsafe_unretained 對應關鍵字unsafe_unretained
    • weak 對應關鍵字weak
  • ARC內部實現

    ARC背後的引用計數主要依賴於三個方法:

    • retain 增長引用計數
    • release 下降引用計數,當引用計數爲0時釋放對象
    • autorelease 在當前的auto release pool結束後,下降引用計數
  • JavaScript垃圾收集器

javaScript 具備垃圾自動收集機制,垃圾收集器會按照固定的時間間隔,週期性地執行這一炒做,具體到瀏覽器的實現,也能夠指定收集時間

  • 垃圾收集的方法

    • 標記清除法 javaScript中最重要的收集方法,給當前不使用的值加上標記,而後等待回收其內存

    • 引用計數(再也不使用)

    • 性能問題 垃圾收集器是週期運行的,並且若是變量分配的內存數量比較大,那麼回收工做量也是至關的大

  • Dart垃圾收集器

Dart的垃圾收集器是分代的,由兩個部分組成:新生代空間收集器、並行標記掃描收集器,還有一個重要的東西,就是調度器

  • 調度器

    在Flutter引擎中,爲了最小化垃圾收集對應用程序和UI性能的印象,與垃圾收集器提供了hook當引擎檢測到應用程序處於空閒狀態(沒有與用戶交互)會發出警報,爲垃圾收集器提供運行其收集階段而不影響性能的機會。而且垃圾收集器能夠在這些空閒時間運行內存壓縮,從而較少內存碎片來優化內存

  • 新生代空間收集器

    此部分相似於Java的複製算法,用於清理壽命較短的對象,例如Stateless部件,雖然是會阻塞線程,但當與調度器結合使用,幾乎感知不到應用程序在運行期間的暫停,從本質上,新建的對象被分配給內存中的連續空間,在新建對象,會被分配到下一個可用空間,直到填充完分配的內存,但Dart使用的是一個凹凸的指針,因此這個過程很是快,分配新對象的空間由兩部分組成,任什麼時候候只用一半,當一半滿後,活動的對象將複製到另外一半空間中,一半就會所有清空,肯定對象是否活動,收集器以根對象開始,進行檢測他們引用的內容,這一部分相似於Java可達性算法,有引用的對象將會被複制到另外一個空間中

  • 並行標記掃描收集器

    當對象達到必定的生命週期時,會被提上到另外一個新的內存空間,由另外一個收集器管理,此收集器有兩個階段:

    • 遍歷對象,標記仍在使用的對象

    • 掃描整個存儲器,並回收未標記的對象,而後清除全部標記

4.總結

由上面所述,Dart的垃圾收集器方式參考了部分語言的實現,但須要注意的是,Dartisolates擁有本身的私有堆,彼此是獨立的,每一個isolates運行在單獨的線程中,每一個ioslates的垃圾收集事件不影響其它isolates的性能,因此isolates能夠避免UI出現卡頓和很好的進行頻繁的回收操做,這就是dart做爲Flutter的主要語言的緣由之一。

參考: 1.Flutter: Don’t Fear the Garbage Collector

相關文章
相關標籤/搜索