内容字号:默认大号超大号

段落设置:段首缩进取消段首缩进

字体设置:切换到微软雅黑切换到宋体

iOS原生应用VS Flutter VS GICXMLLayout比较

2019-01-29 11:16 出处:清屏网 人气: 评论(0

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

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

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

文中用到的测试代码可以直接从这里 点击下载

在做比较之前,先确定一个比较的样例。这里以如下UI内容为例。

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

1. 启动时间

测试平台是 iPhoneX , iOS 12.0 ,因为做的是横向比较,因此不在多设备上进行测试,只在 iPhoneX 上进行测试分析。

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

  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线程 中执行的。考虑到 Flutter app加载了一个 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 两种模式下,包的大小差距会很大。这里分别给出。

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

原生

bitcode
bitcode

GICXMLLayout

bitcode
bitcode

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 语言、甚至其他的脚本语言。


分享给小伙伴们:
本文标签: FlutterGICXMLLayout

相关文章

发表评论愿您的每句评论,都能给大家的生活添色彩,带来共鸣,带来思索,带来快乐。

CopyRight © 2015-2016 QingPingShan.com , All Rights Reserved.