Flutter使用dart
语言做为其开发语言和运行环境。dart
的runtime
是一直存在的,可是在debug
和release
模式下有一些区别。java
debug
模式下,dart
大部分组件都放在设备上,例如runtime
、JIT(Android)
、interpreter(iOS)
、debug
和profile
services
。release
模式下,只剩下runtime
,而这也是Flutter App可以运行起来的最基本组件。在runtime
中,存在一个在初始化对象时为其分配内存,对象再也不被使用的时候回收内存的组件,即GC。 在Flutter
中存在不少对象。以Stateless
Widget
为例,其在State
发生变化或者Widget
不可见的时候不断地发生重建和销毁(注意,此处是指Widget
树中的Widget
,对于Element
树和RenderObject
树来讲,element
和renderObject
是可变的,并且其初始化生成须要消耗不少资源。所以在大多数状况下他们是会被回收利用的)。这些Widget
的生命周期都很短,对于一个UI比较复杂的APP来讲,可能会有数千个Widget
须要被常常回收建立。算法
因此有些开发者可能会采起一些措施来避免太过频繁的GC。好比为了保持一个引用的Widget
对象不会被回收,将其放在state
中(这样并非说真的不会被回收,只是建立回收的频率被下降了,由于state
是属于element
的,而element
的生命周期是比较长的)。less
这么作是没有必要的,首先Widget
是一个很轻量级的对象,它的建立和回收并不会占用不少资源,真正占用资源的是Element
和RenderObject
。其次dart
的GC机制可以快速有效的进行对象回收,不用担忧Widget
建立过多致使OOM
出现。 oop
关于Widget
、Element
、RenderObject
的更多关系请参看这篇文章Flutter中的层级蛋糕。 post
和Jvm相似,dart中的GC是分代的,一个是年轻代,一个是老年代。若是熟悉Jvm内存机制的童鞋能够快速略过这一部分,直接看最下面的结论。性能
首先介绍下dart
中的调度机制:为了最小化GC对APP和UI的性能影响(由于dart的GC有一种相似于JVM中stop the world
的机制,致使APP对事件无响应、UI没法刷新),GC经过与Flutter
的engine
创建联系,在Flutter APP处于空闲、无用户交互、或者在后台的状况下,engine通知GC进行回收工做。这样就不会对APP和UI产生影响了。 同时GC还会使用滑动压缩(相似于JVM中标记整理中的整理)的方法来减小内存碎片的数量,从而减小内存开销。线程
dart
内存中的年轻代和JVM中的年轻代很类似。 年轻代上存放的对象是那些生命周期较短,须要常常建立回收的对象,例如stateless
widget
。年轻代的GC比老年代的频繁不少,速度也比老年代快。配合上schedule机制,咱们在APP运行的时候几乎感受不到GC形成的卡顿。 在本质上,对象占据了内存中的连续空间。随着对象的建立,它们被分配给下一块可用的内存空间,直到全部的内存都被占满了,而后进行GC。dart
使用指针碰撞的方式来给这些对象分配空间(之因此没有空闲列表的方法是由于dart
在GC以后都会采用滑动压缩的方式来把内存碎片清除掉)。 和JVM相似,dart的年轻代也分红两个部分,在任什么时候候,只会有一部分被使用。 debug
from
区域中的对象,判断其是否能够被回收(采用可达性分析方法),遍历完成以后将不会被回收的对象复制到
to
区域中,而后
from
区域中的对象所有被回收掉。最后原来的
to
区域就变成
from
区域。 吐个槽,可能这种回收方式还会修改,改为JVM中8:1:1的方式,由于每次都只能使用一半的内存,实在是太浪费内存了。 再补个图供参考
当对象经历过必定次数的GC仍然存在,或者其生命周期较长(我的猜想相似于element
和RenderObject
这种须要屡次复用,可变且建立比较耗费性能),将其放入老年代区域中。 老年代采用标记整理的方法来回收对象。设计
stop the world
,因此这个时候可能会致使ANR
(只是相似于ANR
的表现,其产生缘由仍是不同的),可是因为dart
优秀的schedule
机制和老年代GC频率很低的缘由,基本上不会出现这个问题。
须要注意的是,若是APP不支持弱年代假设(即大多数对象的生命期都很短;从年老对象到年轻对象的引用很是少),上面的分代设计就不那么有效了,可是考虑到Flutter中的Widget
、Element
、RenderObject
关系,咱们不须要担忧这个问题。指针
与JVM内存模型不一样的是,dart
中每一个isolate
都有本身的内存空间,其各自的GC不会影响到其余isolate
的。因此咱们能够经过把部分占用内存空间较大且生命周期较短的对象方法其余isolate
中,这样即便另一个isolate
GC了,并不会对咱们显示UI的isolate
形成影响。
dart | java | |
---|---|---|
判断对象可被回收算法 | 可达性分析 | 可达性分析 |
年轻代GC算法 | 复制 1:1 | 复制 8:1:1 |
老年代GC算法 | 标记整理 | 标记整理 |
是否发生stop the world | 是 | 是 |