掌握会场页面性能优化,解锁得物技术新境界
2023-10-17 11:38:05
得物App内h5的项目都是通过webview打开。对于webview的性能大家普遍的印象就是打开速度比native慢,甚至有很多认为webview天生的性能就比native慢,基于这个印象,得物在前期的优化工作中,重点关注webview本身的启动速度。随着webview性能的不断提升,得物将优化重点转移到了页面性能上。
会场页面的性能优化与原生对比
在进行页面性能优化之前,得物对webview页面和原生页面的性能表现进行了一个简单的对比。如下表格是它们在关键链路的表现:
关键链路 | webview | native |
---|---|---|
启动时间(冷启动) | 4s | 2s |
首屏时间 | 5s | 3s |
加载完成时间 | 10s | 6s |
从表格中可以看出,除了启动时间外,其他环节webview和native页面的差距都不大,这也就说明了得物的webview优化已经取得了不错的效果。那么webview启动时间为什么比native页面慢?启动时间是webview页面加载的第一步,也是最重要的一步。所以,只要我们能够提升webview的启动时间,整个webview页面的性能表现就会得到较大的提升。
基于对象管理解决内存溢出
在完成对webview启动时间的性能优化后,得物开始着力解决webview内存溢出的问题。得物产品对h5页面资源管理模式一直采用对象管理的方式,在用户跳出后直接杀死进程,并清理释放所有资源,这种方式能够在每次用户请求时保持最干净的状态,尽量减少资源溢出的发生。但是,它也有着非常明显的缺点:用户每次请求都要重新拉起webview并重新加载渲染页面,相比于能够复用资源的缓存方案,对象管理的方式很显然效率较低。那有没有一种方案既能够解决对象的管理问题,又可以实现资源的复用呢?
我们知道得物的webview是由XWalk内核驱动的,在webview加载页面时,XWalk内核会创建进程。这个进程可以理解为一个独立的沙箱环境,每个webview都会创建唯一的进程。而浏览器、原生都是由系统原生webview组件WebView承载的,Android native应用启动速度慢的原因也是在创建进程上。
WebView的进程是系统管理的,WebView进程的创建与WebView的显示没有任何关系,也就是说WebView可能在后台已经创建好了,也可能还没创建。
为了解决这个问题,Android native应用在创建一个新的WebView的时候都会首先检测进程是否存在,如果进程已经存在就复用,如果不存在就创建。复用webview,可以节省进程创建的时间,对于启动性能的提升也很明显。
启动优化小结
-
首先会检查是否有可用进程(先由主进程创建XWalkService),然后和Service通讯检查是否有可用进程,如果XWalkService已经创建进程,且XWalkService还存活,就能直接复用,避免了反复的进程创建和销毁;
-
杀死进程,并释放资源,这里使用了flushInstrumentation来间接杀死进程,flushInstrumentation是系统提供的同步杀死进程的接口,确保进程的释放没有延时,不会造成资源泄露,也不会影响到其他组件的使用;
-
创建新进程和初始化webview,如果没有可用进程,就创建一个新的XWalkService并拉起一个新的进程;
-
绑定webview到进程,如果进程已经存在,直接绑定,如果不存在,监听WebViewClient回调,在页面加载完毕后,初始化完成,绑定webview到进程,这样也能起到优化首屏加载时间的作用。
实施结果
优化后,得物webivew启动时间有了明显的提升,启动时间从冷启动4s降低到1s,相较于native页面的启动时间2s,差距缩短到1s。在首屏渲染时间和加载完成时间上,得物webview和native页面的差距也进一步缩小。
关键链路 | webview | native |
---|---|---|
启动时间(冷启动) | 1s | 2s |
首屏时间 | 3.5s | 3s |
加载完成时间 | 7s | 6s |
此外,得物的webview内存溢出问题也得到了很好的解决。在对象管理的方式下,用户的体验很不流畅,页面资源容易在用户不知情的情况下被直接释放掉。而在采取进程复用的方案后,用户在使用得物App内的h5页面时会明显感到流畅度得到了很大的提升,再也没有遇到过页面资源被释放导致闪退的情况,这也间接地证明了进程复用这一方案的有效性。