iOS:原生应用 VS Flutter VS GICXMLLayout 比较

最近,有些朋友问我,到底GICXMLLayout的性能如何?所以有了本篇文章。另外,考虑到如今Flutter也比较火,为了避免藏私,所以也加入对Flutter的比较。所以这里详细的对三种开发方式进行横向比较。前端

注1:flutter采用的是最新的1.0.0版本。git

注2:flutter的测试都在profile模式下测试,性能接近releasegithub

文中用到的测试代码能够直接从这里点击下载缓存

在作比较以前,先肯定一个比较的样例。这里以以下UI内容为例。bash

这里面给出了一个显示可变高度的列表的案例,这样的案例比较具备通用性,有图片的加载、有高度不固定文本的显示、有高度不固定CellHeight的计算等等。下面针对这样的案例,从各类角度来比较分析在不一样的开发方式下的比较。架构

1. 启动时间

测试平台是iPhoneX,iOS 12.0,由于作的是横向比较,所以不在多设备上进行测试,只在iPhoneX上进行测试分析。app

启动时间的比较由两个方面组成。iphone

  1. main以前

    main函数以前的时间表示的是iOS对动态连接库的加载、系统加载等所耗时间。这个时间经过添加DYLD_PRINT_STATISTICS宏来得到。函数

  2. main函数以后

    main函数以后的时间经过main函数和applicationDidBecomeActive:方法的时间差来得到。布局

另外,为了公平起见,测试方式采用的profile的方式测试。

主要是考虑到Flutterreleasedebug两种模式下的性能差别太大,而releaseprofile两种模式很接近,所以采用profile的方式

另外,测试加载的数据为11条,时间单位为(秒)

原生

main函数以前的时间范例

Total pre-main time: 205.82 milliseconds (100.0%)
         dylib loading time: 191.47 milliseconds (93.0%)
        rebase/binding time:   0.29 milliseconds (0.1%)
            ObjC setup time:   6.29 milliseconds (3.0%)
           initializer time:   7.76 milliseconds (3.7%)
           slowest intializers :
             libSystem.B.dylib :   4.67 milliseconds (2.2%)
复制代码
main以前 mian以后 总计
0.201 0.099 0.3
0.206 0.086 0.292
0.210 0.092 0.302
0.197 0.089 0.286
0.195 0.098 0.293
平均 0.294

以上数据是原生APP的启动时间,平均0.294秒

GICXMLLayout

main函数以前的时间范例

Total pre-main time: 342.71 milliseconds (100.0%)
         dylib loading time: 291.83 milliseconds (85.1%)
        rebase/binding time:   1.55 milliseconds (0.4%)
            ObjC setup time:  15
.76 milliseconds (4.5%)
           initializer time:  33.48 milliseconds (9.7%)
           slowest intializers :
             libSystem.B.dylib :   7.05 milliseconds (2.0%)
               AsyncDisplayKit :  42.27 milliseconds (12.3%)
复制代码
main以前 mian以后 总计
0.318 0.066 0.384
0.342 0.069 0.411
0.338 0.066 0.404
0.337 0.067 0.404
0.330 0.064 0.394
平均 0.399

Flutter

main函数以前的执行时间范例

Total pre-main time: 206.08 milliseconds (100.0%)
         dylib loading time: 189.66 milliseconds (92.0%)
        rebase/binding time:   0.82 milliseconds (0.3%)
            ObjC setup time:   7.52 milliseconds (3.6%)
           initializer time:   8.06 milliseconds (3.9%)
           slowest intializers :
             libSystem.B.dylib :   4.61 milliseconds (2.2%)
复制代码
main以前 mian以后 总计
0.218 0.115 0.333
0.203 0.105 0.308
0.209 0.113 0.322
0.211 0.110 0.321
0.203 0.107 0.310
平均 0.319

分析

经过以上三种开发方式的数据分析能够看出,

  1. 启动时间最短的是原生应用,最长的是GIC的应用。
  2. GIC之因此最长,是由于在main函数以前加载了太多的第三方库,可是能够看到main函数以后的执行时间是最短的。
  3. flutterrelease模式下的main函数以前的加载时间跟原生应用能够说相差无几,从这里能够看出,大厂就是大厂,技术能力不得不服。
  4. fluttermain函数以后的执行时间是三种方式中是最长的。

    flutter的引擎、UI、GPU相关的操做都有专门的线程负责,区别于iOS中的UI线程。而fluttermain函数以后的执行时间倒是最长的,那么说明,flutter有些初始化操做多是在iOS的UI线程中执行的。考虑到Flutterapp加载了一个Flutter.framework,而且包含了对iOS平台调用的代码(FlutterAppDelegateFlutterViewController等),所以初步判断是这个库中的代码的执行结果。

  5. GICmain以后执行时间最短应该说是情理之中,由于GIC的列表布局渲染等都在非UI线程执行的(得益于Texture)。也就是说,GIC在UI线程上作的事情是在三种开发方式中最少的。

从这里也能够看出,GIC的问题在于对第三方库的依赖太多,后续考虑如何减小对第三方库的依赖,事实上目前已经在作对RAC库的剥离工做,相信剥离后会进一步的提高加载速度。

原生应用在加载列表的时候采用的是最粗暴的方法,没有任何的优化,没有height缓存,没有在后台线程作height计算等等,所以原生应用在启动时间方面也有进一步的优化空间。可是排名不会发生变化,最多就是mian函数后的执行时间会缩短,但不会短过GIC

2. 帧率CPUGPU

这三项数据的测试在iPhoneX上看不出明显的不一样,所以这里就以iphone 6的测试数据为准。

测试方式:不停的滑动列表

原生

GICXMLLayout

flutter

分析

  1. 帧率:

    在帧率方面,三种方式都差很少,基本上都能维持满帧。

  2. CPU:

    CPU占用率从高到低排名为:flutter(平均14%) > 原生(平均10%) > GIC(平均7%)。

  3. GPU:

    GPU占用率从高到低排名为:flutter(平均22%) > 原生(平均16%) > GIC(平均12%)。跟CPU的结果差很少,flutter在滑动的时候GPU耗费也高达22%,比最低的GIC差很少高了一倍。

这一轮的测试中,flutter基本上算是完败了,不是百分之多少的差距,而是成倍的差距。

GIC在UI层是基于Textrue开发的,所以继承了Textrue的全部优势。在这一轮测试中能够说完胜。

3. 内存占用

测试方式:页面加载完成后滑动列表,而后静置一段时间 测试设备:iphone6

原生

GICXMLLayout

flutter

flutter依然是以profile模式测试。

分析

由上面三张图看出,flutter(40MB)占用的内存最多,GIC(13.7MB)次之,原生(9MB)应用占用最少。

  1. 能够看出flutter占用了40MB,比原生应用多了将近3倍都不止。
  2. GIC占用了13.7MB

    因为GIC在基于Texuture封装的时候把布局元素也做为UI元素封装了,所以致使实际的内存占用稍微高了点。

另外,GIC在使用的过程当中建立了JSContext,你能够理解为JS引擎。而在实际使用过程当中,JS并无占用太多的内存。固然,这里面涉及到JS功能也比较少,所以也没法直接说JS占用内存地。

4. 包大小。

为了公平起见,这里的测试基于release模式下测试。另外,在打开和关闭bitcode两种模式下,包的大小差距会很大。这里分别给出。

另外,测试应用已经踢除了静态图片资源。

原生

  1. 打开bitcode:1.1MB
  2. 关闭bitcode:269KB

GICXMLLayout

  1. 打开bitcode:16.2MB
  2. 关闭bitcode:3.7MB

flutter

flutter自己就不支持bitcode。所以忽略bitcode。包的大小为:11MB

分析

经过上面的数据能够分析出,在关闭bitcode的状况下,包的大小依次为,flutter(11MB) > GIC(3.7MB) > 原生(269KB)。

5. 动画

这里以一个简单的水平位移动画做为案例。

测试设备:iphone6

原生

使用CABasicAnimation作动画。

GICXMLLayout

flutter

分析

对于这么简单的动画,都是满帧运行的。所以只须要对GPU和CPU作分析比较便可。

  1. 原生:

    原生方式的性能表现是最好的。在动画的时候,几乎不占用CPU资源。而GPU一直保持着7%的占用。

  2. GICXMLLayout:

    GIC的GPU的占用上跟原生的差很少,可是CPU却一直有占用,差很少维持着最高10%的占用。而且能够注意到,CPU的占用不是连续的而是断断续续的,这是有缘由的,由于GIC的动画是基于popAnimation实现的,而popAnimation是基于CADisplaylink开发的,而且是按照60帧计算的。也就是差很少每秒60次的动画计算。而只有在动画计算的时候才会占用CPU资源,所以从测试结果来看,也是符合预期的。另外,在内存占用方面,跟原生动画差很少。

  3. flutter

    flutter的动画在GPU的占用上几乎是原生的两倍以上。并且CPU也是连续维持着10%的占用。而内存占用方面也差很少是原生的两倍以上。

总结

在上面的测试中,因为测试案例比较简单,并不能表明大多数状况,只是针对当前的测试案例得出的结果,仅仅只是给出一个参考。

对于原生引用的测试代码可能有点不公平,没有进行任何的优化。然而这并非关键,这样正说明了原生应用的优化空间比较大。

原本还想作一个列表加载时间测试的,可是对于flutter却无从下手,暂时不知道如何测试,等之后有方法了再作测试。

另外,这里也不得不为我本身的GICXMLLayout作个宣传。做为一个独立开发者维护的一个开源库并不容易,我花了不少的心血在这上面。各位,若是以为GIC这个库还能够,还但愿能给个star,感谢!项目地址

抛开原生应用不谈,若是您想像前端开发同样开发IOS应用,那么我以为GIC值得您一试。无论从开发效率、上手难度、代码可读性等方面来讲,GIC都能有优秀的表现,而GIC目前相较于flutter等支持跨平台的库来讲最大的缺点是不支持跨平台。若是您开发的应用不考虑跨平台开发的话,那么GIC是一个很好的选择。

有的朋友可能会说,如今flutter很流行,而且dart的效率比JS高。可是GICUI业务逻辑(ViewModel)上是两套彻底不一样的架构,UI是纯native的而且是基于Texuture开发的,而ViewModel你既可使用native代码来写,也支持使用JS来写。另外在实际的应用(非游戏)开发中,业务逻辑若是复杂到能经过不一样的语言来区分的地步(好比dart和JS),那么这样的应用应该是一个很是复杂的应用了。所以我认为在语言上来比较孰优孰虑并非最优先级。另外,事实上GIC从架构设计上其实也能够支持dart语言、甚至其余的脚本语言。

相关文章
相关标签/搜索