如何把一个静态网站,wordpress 创建报错,建设教育信息网站工作总结,郑州小程序开发公司排名背景
论坛上很多小伙伴关心为什么闲鱼选择了Flutter而不选择其他跨端方案#xff1f;站在质量的角度#xff0c;高性能是一个很重的因素#xff0c;我们使用Flutter重写了宝贝详情页之后#xff0c;对比了Flutter和Native详情页的性能表现#xff0c;结论是中高端机型上F…背景
论坛上很多小伙伴关心为什么闲鱼选择了Flutter而不选择其他跨端方案站在质量的角度高性能是一个很重的因素我们使用Flutter重写了宝贝详情页之后对比了Flutter和Native详情页的性能表现结论是中高端机型上Flutter和Native不相上下在低端机型上Flutter会比Native更加的流畅其实闲鱼团队在使用Flutter做详情页过程中没有更多地关注性能优化为了更快地上线也是优先功能的实现不过测试结果出来之后却出乎意料地优于原先的Native的实现(具体的测试结果属于敏感数据要走披露流程伤不起…)
但是这样很显然不能敷衍过去仔细想了想确实Flutter的定位并不是要替代Native他只想做一个极致的跨端解决方案所以还是要回到跨端解决方案的赛道给您从性能角度比一比谁才是更好的跨端开发方案
参赛选手
[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.
[REACT NATIVE]
Were 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分别实现的一个实际可用的AppCar Guo谦虚表示其实也写的比较粗糙但是在我看来这个是具备真实使用场景的AppGithub客户端App提供丰富的功能旨在更好的日常管理和维护个人Github还是有代表性的 [Flutter] https://github.com/CarGuo/GSYGithubAppFlutter [REACT NATIVE] https://github.com/CarGuo/GSYGithubApp
场景
1、默认登录成功 2、“动态”页点击搜索按钮搜索关键字“Java”正常速度浏览3页等第4页加载完成后回退 3、点击“趋势”页Tab浏览Feeds到页面底部点击最底部的Item进入Item后浏览详情浏览3页的动态后回退到“我的”Tab页 4、查看“我的”Feeds到底部点击右上角搜索按钮搜索关键字“C”浏览3页后等第4页加载完成后场景结束
测试工具
iOS掌中测(iOS端)CPU内存InstrumentsFPSAndroid基于Adb的Shell脚本CPU内存FPS
测试机型
iOSiPhone 5c 9.0.1 / iPhone 6s 10.3.2AndroidXiaomi 2s 5.0.2 / Sumsung S8 7.0
数据分析
iOS
iPhone 5c 9.0.1 iPhone 6s 10.3.2 测试结论
1、Flutter在低端和中端的iOS机型上FPS的表现都优于RN 2、CPU的使用上Flutter在低端机上表现略差于RN中端机型略优于RN 3、值得注意的是内存上的表现(上图红色箭头区域)Flutter在低端机型上的起始内存和RN几乎一致在中端机型上会多30M左右的内存(分析为Dart VM的内存)可以想到这应该是Flutter针对低端和中端机型上内存策略是不一样的可用内存少的机型Dart VM的初始内存少运行时进行分配(这样也可以理解为什么在低端机上带来了更多的CPU损耗)中端机器上预分配了更多的VM内存这样在处理时会更加的游刃有余减少CPU的介入带来更流畅的体验. 可以看出Flutter团队在针对不同机型上处理更加的细腻目的就是为了带来稳定流畅的体验。
Android
Xiaomi 2s 5.0.2 Sumsung S8 7.0 注: MFS - Max Frame Space: 指的是去掉buffer之后的两帧的时间差
测试结论
1、Flutter在高低端机的CPU上的表现都优于RN尤其在低端的小米2s上有着更优的表现 2、Android端在原来FPS基础上增加了流畅度的指标FPS和流畅度的表现Flutter优于RN(计算规则见附参考文章) 3、Android端的内存也是值得关注的一点在小米2s上起始内存Flutter明显比RN多40MRN在测试过程中内存飞涨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流畅度: https://testerhome.com/topics/4775Android 内存获取方式:dumpsys meminfo packageNameAndroid 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;
原文链接 本文为云栖社区原创内容未经允许不得转载。