SGADC2019APP淘宝如何做到又快又稳?

2022-03-31 13:44:18 浏览数 (1)

手机淘宝在双十一等大促期间承载着非常多且复杂的业务,众多玩法将手淘变成购物 游戏 小视频 直播 浏览器综合在一起的超级APP,如何保证这个超级APP能够快速且稳定运行?

11月19日,在软件绿色联盟开发者大会安全、性能与体验优化分论坛上,应用启动稳定性两个核心场景为大家分享了手淘体验优化过程中的实践与思考。

手淘体验之路

手机淘宝技术架构发展经历了四个重要的年份:2013年,阿里巴巴制定All in 无线战略,技术架构从B/S转向C/S,集中打造移动基础设施;2015年是手机淘宝跨平台开发的一年,客户端的容器化、动态化,上线节奏大幅提升,实现了生产力飞跃;2017年是手机淘宝内存优化的一年,新交互方式的涌起,直播、短视频、AR、VR等应用快速落地,移动端面临着内存不足的挑战;2019年是手机淘宝迈向极致体验的一年,AI技术和小程序(轻应用)大量落地,技术推动体验提升。

启动场景优化

启动是非常复杂的一个场景,它的核心要求是快。在启动过程中,手机淘宝面临着“黑科技”、“高并发”、“负载集中”和业务复杂等诸多挑战。

手淘技术团队从应用架构优化、系统能力突破和硬件能力提升三个层面对淘宝的启动性能进行优化。从下图可以看到,在每个层面手机淘宝都做了很多优化工作,下面对应用层的启动框架、系统层的预编和硬件层的CPU频率的调节进行重点分享。

1、应用层优化

(1)启动过程分析

这个是一个常见的性能分析图,可以发现,启动时CPU调用的时间只有1.39毫秒,但实际执行时间达到了超过了300ms。而这个构造函数实际非常简单,主要原因还是由于启动过程负载非常集中造成的。

(2)任务与资源编排

首先进行阶段划分,将启动过程分为基础库运行、UI运行阶段,资源预加载阶段和闲时任务阶段;其次严格梳理160个任务之间的依赖关系,构建有向无环图,将任务精心编排至相应阶段;最后进行任务调度,设置合理的线程池大小及优先级,基础库阶段与 UI 运行库阶段线程优先级最高,同时建立等待机制,保证阶段的有序执行。通过下图可以看到,最终优化后,每个阶段执行的任务数量。

如下,经过阶段划分后可以得到启动框架所构成的阶段序列拓扑图。横坐标代表应用的启动时间和启动过程,纵坐标代表着每一个任务的时间,相当于将启动模式可视化,从而发现瓶颈在哪里。

2、系统层优化

安卓5.0以后,谷歌为了提升代码运行效率,推出了安装时全量编译的方式,将所有的代码编译成二进制文件,导致安装时间长、应用占用空间变大、耗电、性能降低等问题。在安卓7.0之后,谷歌推出了混合编译的方式,通过分析识别“热代码”和预加载等方式,既可以提升编译速度,又可以保证安装包的大小。

对于启动过程的代码,由于执行次数较少,无法自动识别为热代码进行提前编译的。但是借助这个机制,手淘通过手动的方式,将启动过程中运行的类和方法加载到Profile中,极大地提升了启动速度。测试结果显示,性能提升20%到30%。

3、硬件层优化

一般情况下,手机有性能模式、平衡模式和省电模式三种电源管理模式,其本质是对屏幕、CPU等硬件的调节。它对硬件的管理是不智能的,如何去改变这种状态呢?

除了不同的电源管理模式,CPU架构设计中还有大小核的概念,大核频率高,运算能力强,而小核则相对性能较差,但是比较省电。因此,为了保证运行效率,我们需要把主线程绑定在大核上。我们通过和硬件厂商进行合作,将梳理出来的核心场景(比如启动、直播、互动和扫码等)与手机系统建立通信,让手机根据核心场景的状态对CPU等硬件资源进行动态调节。比如启动时调高CPU的频率,启动完成时再回到初始状态,这样只需要一个很短的时间,就可以获得10%到20%的性能提升,而且对手机续航不会有很大影响。

稳定性保障

1、稳定性面临的挑战

通过下图可以看到,在大促期间,手机淘宝会有很多玩法,业务非常多而且复杂,它把手淘变成购物APP 游戏APP 小视频APP 直播APP 浏览器APP综合在一起的超级APP。在堆栈上面看就是Native H5 weex等各种技术栈的综合应用,这就面临着内存不足的挑战。

在面试的时候,你可能会遇到这样的问题,一个APP最多能够使用多少内存?其实APP的内存不止一个,它可以分为VSS、RSS、PSS等,通常遇到的内存不足是指VSS不足。而VSS在32位的操作系统中,它的一个内置的选址空间只有32位,也就意味着内存上限是4G,是无法满足复杂场景的需求的。

2、多进程架构

内存不足了,如何使用更多的内存?手淘采用多线程的方式来解决。通过下图可以看到淘宝主进程的基础框架。手淘通过配置文件对业务进程进行管理,比如淘宝人生这种相对独立的游戏将它放到独立的进程中去,类似的还有轻应用和小应用也会放在独立进程中。同时,手淘还设计了一套IPC通信的机制,比如说弹窗、数据统计等,把子进程产生的数据通过IPC传到基础框架。

3、设备分级

多线程解决的是内存使用效率的问题,那么如何减少内存使用的总量问题呢?手淘采用设备分级的方式,将设备分为高、中、低端,根据设备性分级匹配不同的视觉特效,确保使用的流畅性。

这个方案的难点在于,安卓生态非常复杂,如何恰当的对数万款设备进行分级?手淘设计了一套智能化算法,采集手机的CPU频率、GPU频率、内存等硬件指标,以及手淘启动时间、页面性能、卡顿次数等数据,通过模型运算,就可以一个全量的设备分级表。如下图所示,可以发现分级结果与启动性能正相关,性能越好的设备,启动越快。

4、自动容灾技术

除了节省内存之外,手淘还做了一些主动防御工作来确保应用的稳定性,即主动测试当前手机内存水位,并根据水位情况执行响应的内存优化策略。

容灾控制器通过物理内存监听的方式对内存水位进行计算,并将内存水位情况通知到注册的业务中去,使之执行响应的内存策略。

通过下图可以看到,自动内存容灾策略上线后的效果, OOM次数明显降低。

写在最后

探讨:性能优化到什么程度是合适的呢?

我做了一个模型,横坐标是功能,即软件为用户解决的需求,纵坐标是体验,即用户的使用感知。体验是不影响功能的使用的。所以如果我们把技术指标与业务指标进行关联,我们就可以看到一个性能优化得到了多少业务指标的提升。从而衡量你愿意为这个业务指标的提升付出的成本,从而决定是否要进行优化。

最后送给大家一句话,与大家共勉:存在感最低的技术团队是最优秀的。因为用户在使用软件的过程中,如丝般顺滑的话是感觉不到技术人员的存在的。

End

0 人点赞