流言终结者- Flutter和RN谁才是更好的跨端开发方案?

做者:闲鱼技术-灯阳android

背景

论坛上不少小伙伴关心为何闲鱼选择了Flutter而不选择其余跨端方案?站在质量的角度,高性能是一个很重的因素,咱们使用Flutter重写了宝贝详情页以后,对比了Flutter和Native详情页的性能表现,结论是中高端机型上Flutter和Native不相上下,在低端机型上,Flutter会比Native更加的流畅,其实闲鱼团队在使用Flutter作详情页过程当中,没有更多地关注性能优化,为了更快地上线,也是优先功能的实现,不过测试结果出来以后,却出乎意料地优于原先的Native的实现(具体的测试结果,属于敏感数据,要走披露流程,伤不起…)git

可是这样很显然不能敷衍过去,仔细想了想,确实Flutter的定位并非要替代Native,他只想作一个极致的跨端解决方案,因此仍是要回到跨端解决方案的赛道,给您从性能角度比一比,谁才是更好的跨端开发方案?github

参赛选手

[Flutter]

Flutter is Google’s mobile app SDK for crafting high-quality native interfaces on iOS and Android in record time. Flutter works with existing code, is used by developers and organizations around the world, and is free and open source.objective-c

[REACT NATIVE]

We're working on a large-scale rearchitecture of React Native to make it more flexible and integrate better with native infrastructure in hybrid JavaScript/native apps.编程

鸣锣开赛

怎么比

怎么比较确实伤脑筋,本身也写了一个Flutter 和 一个RN的App,可是实在太丑陋,担忧你们关注点都到个人烂代码上了,因此在Github上找到了一个跨端开发高手Car Guo,用Flutter和RN分别实现的一个实际可用的App,Car Guo谦虚表示其实也写的比较粗糙,可是在我看来这个是具有真实使用场景的App(Github客户端App,提供丰富的功能,旨在更好的平常管理和维护我的Github),仍是有表明性的 [Flutter] github.com/CarGuo/GSYG… [REACT NATIVE] github.com/CarGuo/GSYG…性能优化

场景

一、默认登陆成功 二、“动态”页,点击搜索按钮,搜索关键字“Java”,正常速度浏览3页,等第4页加载完成后回退 三、点击“趋势”页Tab,浏览Feeds到页面底部,点击最底部的Item,进入Item后,浏览详情+浏览3页的动态后回退,到“个人”Tab页 四、查看“个人”Feeds到底部,点击右上角搜索按钮,搜索关键字“C”,浏览3页后,等第4页加载完成后场景结束app

测试工具

  • iOS
  • 掌中测(iOS端):CPU,内存
  • Instruments:FPS
  • Android
  • 基于Adb的Shell脚本:CPU,内存,FPS

测试机型

  • iOS:iPhone 5c 9.0.1 / iPhone 6s 10.3.2
  • Android:Xiaomi 2s 5.0.2 / Sumsung S8 7.0

数据分析

iOS

iPhone 5c 9.0.1

image.png

iPhone 6s 10.3.2

image.png

测试结论

一、Flutter在低端和中端的iOS机型上,FPS的表现都优于RN 二、CPU的使用上Flutter在低端机上表现略差于RN,中端机型略优于RN 三、值得注意的是内存上的表现(上图红色箭头区域),Flutter在低端机型上的起始内存和RN几乎一致,在中端机型上会多30M左右的内存(分析为Dart VM的内存),能够想到这应该是Flutter针对低端和中端机型上内存策略是不同的,可用内存少的机型,Dart VM的初始内存少,运行时进行分配(这样也能够理解为何在低端机上带来了更多的CPU损耗),中端机器上预分配了更多的VM内存,这样在处理时会更加的游刃有余,减小CPU的介入,带来更流畅的体验. 能够看出,Flutter团队在针对不一样机型上处理更加的细腻,目的就是为了带来稳定流畅的体验。ide

Android

Xiaomi 2s 5.0.2

image.png

Sumsung S8 7.0

image.png

  • 注: MFS - Max Frame Space: 指的是去掉buffer以后的两帧的时间差

测试结论

一、Flutter在高低端机的CPU上的表现都优于RN,尤为在低端的小米2s上有着更优的表现 二、Android端在原来FPS基础上增长了流畅度的指标,FPS和流畅度的表现Flutter优于RN(计算规则见附参考文章) 三、Android端的内存也是值得关注的一点,在小米2s上起始内存Flutter明显比RN多40M,RN在测试过程当中内存飞涨,Flutter相比之下会更稳定,内存上RN侧的代码是须要调优的,同一套代码Flutter在Android和iOS上并无很大的差别,可是RN的却要在单端调优,Flutter在这项比拼上又更胜一筹。 比较奇怪的是三星S8上Flutter和RN的初始内存是一致的,猜想是RN也Android高端机型上也会预分配一些内存,具体细节还须要更进一步的研究。工具

升旗仪式

看了以前的数据,作为裁判的我会把金牌颁给Flutter,在测试过程当中的体验和数据上来看Flutter都优于RN,而且开发这个App的是一位Android的开发同窗,Flutter和RN对于他来讲都是全新的技术栈,Car Guo同窗更倾向性地让你们获得一致性的使用体验,性能方面并无投入太多的时间进行调优,由此看出Flutter在跨端开发上在一样投入的状况下,能够得到更佳的性能,更好的用户体验。性能

一些思考

拿到了这些数据,也感觉到Flutter带来福利,那Flutter为何能够作到这么流畅呢?Flutter是如何优化了渲染,Dart VM的Runtime是怎么玩的?请你们继续关注后续解密文章,感兴趣的同窗欢迎加入闲鱼,成为跨端解决方案的领军者。

参考

  • Android FPS&流畅度: testerhome.com/topics/4775

  • Android 内存获取方式: dumpsys meminfo packageName

  • Android CPU 经过busybox 执行 top命令获取

  • iOS CPU获取方式:累计每一个线程中的CPU利用率

for (j = 0; j < thread_count; j++)
{
ATCPUDO *cpuDO = [[ATCPUDO alloc] init];
char name[256];
pthread_t pt = pthread_from_mach_thread_np(thread_list[j]);
if (pt) {
name[0] = '\0';
__unused int rc = pthread_getname_np(pt, name, sizeof name);
cpuDO.threadid = thread_list[j];
cpuDO.identify = [NSString stringWithFormat:@"%s",name];
} 
thread_info_count = THREAD_INFO_MAX;
kr = thread_info(thread_list[j], THREAD_BASIC_INFO,(thread_info_t)thinfo, &thread_info_count);
if (kr != KERN_SUCCESS) {
return nil;
}
basic_info_th = (thread_basic_info_t)thinfo;
if (!(basic_info_th->flags & TH_FLAGS_IDLE)) {
tot_sec = tot_sec + basic_info_th->user_time.seconds + basic_info_th->system_time.seconds;
tot_usec = tot_usec + basic_info_th->system_time.microseconds + basic_info_th->system_time.microseconds;
tot_cpu = tot_cpu + basic_info_th->cpu_usage / (float)TH_USAGE_SCALE * 100.0;
cpuDO.usage = basic_info_th->cpu_usage / (float)TH_USAGE_SCALE * 100.0;
if (container) {
[container addObject:cpuDO];
}
}
} // for each thread
复制代码
  • iOS 内存获取方式:测试过程当中使用的是phys_footprint,是最准确的物理内存,不少开源软件用的是resident_size(这个值表明的是常驻内存,并不能很好地表现出真实内存变化,这能够另开文章细谈)
if ([[UIDevice currentDevice].systemVersion intValue] < 10) {
kern_return_t kr;
mach_msg_type_number_t info_count;
task_vm_info_data_t vm_info;
info_count = TASK_VM_INFO_COUNT;
kr = task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info,&info_count);
if (kr == KERN_SUCCESS) {
return (vm_size_t)(vm_info.internal + vm_info.compressed - vm_info.purgeable_volatile_pmap);
}
return 0;
}

task_vm_info_data_t vmInfo;
mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
kern_return_t result = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
if (result != KERN_SUCCESS)
return 0;
return (vm_size_t)vmInfo.phys_footprint;
复制代码

联系咱们

若是对文本的内容有疑问或指正,欢迎告知咱们。

闲鱼技术团队是一只短小精悍的工程技术团队。咱们不只关注于业务问题的有效解决,同时咱们在推进打破技术栈分工限制(android/iOS/Html5/Server 编程模型和语言的统一)、计算机视觉技术在移动终端上的前沿实践工做。做为闲鱼技术团队的软件工程师,您有机会去展现您全部的才能和勇气,在整个产品的演进和用户问题解决中证实技术发展是改变生活方式的动力。

简历投递:guicai.gxy@alibaba-inc.com

相关文章
相关标签/搜索