TV端Web页面性能优化实践

01

   背景

随着互联网技术的持续创新和电视行业的高速发展,通过电视观看在线视频已经逐渐成为大众的重要娱乐方式。奇异果App作为在TV设备上用户活跃度最高的应用之一,为广大用户提供了丰富的内容播放服务,除此之外,同样有会员运营、专题活动等上线效率要求极高的服务提供给用户。为满足后者的诉求,我们调研了目前主流的动态化和跨端技术:H5、Flutter 和 React Native,最终从开发效率、人力成本、动态能力和性能上选择用H5方案,目前,H5页面承担了奇异果App内大量的收银、运营活动、专题等业务。然而,H5页面在TV设备上加载耗时过长是我们面临的主要困难,如何提升 H5页面在TV设备上的用户体验,是我们迫切需要解决的问题。

02

   面临的挑战

挑战1:TV设备换机周期较长,系统碎片化问题严重,目前TV端 5.0系统以下的设备占比约 30%,占比很高。优化首先面临的是版本的跨度,兼容低版本是首要考虑。下图为TV端系统版本占比情况:

f73dcacd50a2cadf51cb2990ce9d284a.png

挑战2:TV设备性能偏低,TV设备主要分为三种:电视、盒子和投影仪,以上设备的的配置严重低于同时期的主流手机配置,在我们的性能等级划分中,CPU为4核A53架构且内存超过1.5G就已可划分为高性能设备,在低性能设备中,仍存在较多A7架构处理器或内存为512M的设备。

挑战3:App版本碎片化严重,由于电视行业合作现状的复杂性,渠道较多;传统电视厂商追求稳定,对于升级较为慎重;有较多廉价设备在售,且售出后接近不维护状态;合作模式的复杂导致定制较多,升级困难,对SDK层面的优化和上线有较大挑战。

03

   优化历程


1、准备工作

在优化之前,最重要的工作是统一性能口径、制定统计指标。在口径层面上我们没有采取常规的前端页面加载耗时,采取了更符合用户真实体验的场景:从用户点击按钮开始到真正用户可见。虽然这样会导致我们统计的指标整体耗时增加,但评估后这个指标更利于我们后续优化工作的方向展开。指标口径说明如下

1)页面可见耗时:从客户端点击开始—>客户端页面跳转—>web容器初始化—>前端DOM渲染完成可见。

2)可交互总耗时:页面可见耗时 + 可响应用户遥控器按键总时间。

3)native页面耗时:客户端页面跳转耗时。

4)webview初始化:web容器初始化耗时。

5)调用h5耗时:loadUrl到h5开始执行第一行代码耗时。

6)h5加载耗时:h5开始执行第一行代码到页面可见耗时。

7)h5可交互耗时:h5页面可见到页面可响应耗时。

统计口径统一后,我们在webSDK层面对以上时间点进行投递,并回收线上数据,根据指标反馈的问题进行针对性的优化。在未经优化的情况下,H5的加载速度平均约为 5.5 秒左右,用户体验很差。通过线上数据分析H5加载耗时在整体占比较大,优化H5加载耗时是我们亟需解决的问题。


2、H5加载耗时优化

H5加载耗时主要依赖于前端部分的优化,由于文章篇幅有限,常规的H5页面优化工作不再赘述,如:

1) 资源合并

2) 数据请求合并

3) 业务逻辑优化

4) DOM结构优化

5) 同地址下不同模式Async路由化加载

3、SSR优化

除以上优化之外,SSR(服务器端预渲染)技术进入我们的视线之内,SSR是一种优化Web应用性能和SEO的技术,通过在服务器端生成初始HTML,提高了页面加载速度、搜索引擎优化和用户体验。通过选择适合的框架、创建路由、编写组件、服务器配置和数据获取,开发人员可以实现服务器端渲染,从而为用户提供更好的Web应用体验,保证首屏更快的渲染。

这种降低端上处理压力的方式,非常适合TV端设备性能较差的场景。SSR虽然也有自己的缺点,如虽然可以提高页面整体加载速度,但不利于页面的渐进加载。经过反复实验和线上数据,我们仍然认为SSR的收益整体是正向的,并研发上线。实验证明,SSR方案显著提升了H5页面加载速度。

68652cc1560bb8f4cc1a53cb7bd0369a.png

通过SSR优化后的H5页面加载流程如下图所示:

94dca63b54d5076869e43fb48f49dcc9.png

经过前端上述方案优化后,各个版本的加载速度都得到了显著提升。H5渲染部分的耗时从平均4秒减少至1.5s以下,总耗时减少至3.5秒左右。此时,单纯从前端角度继续优化遇到了瓶颈,投入产出比也较低,需要从客户端整体角度上继续思考优化手段。

4、资源离线缓存

CDN会部署一些关键的H5资源(如css、js、png、ttf等),其中有不少是在前端版本周期内不变的,且较大,客户端在适当的时候进行预下载。在渲染页面时,我们可以利用 WebView内核的 shouldInterceptRequest 回调来拦截在线 H5 URL 的加载请求,如果离线缓存中没有找到该资源,那么就通过在线网络进行加载;如果离线缓存中找到了该资源,则直接从本地磁盘读取资源,返回给 WebView。这种方法能够较大提升加载资源的速度。

离线缓存方案的大致流程图如下:

74bb3d6113aa8c33281779b1c97b0830.jpeg

同时在做的过程中我们发现在低版本上Android原生的请求库HttpUrlConnection还处于http1.0的阶段,不能享受http2.0的优化(如通道复用),这就使得预加载时的请求耗时较高。而TV端目前还有大量版本为5.0以下的低版本设备,因此我们选择了切换到TV端自主研发的网络库,这个网络库支持http2.0,从而提升了低版本设备的请求性能。另外我们看到从用户点击到H5页面打开是有一定的系统调度时间,这个时间也是可以用来做优化的即下面说的并行加载。

5、并行加载

除了上述提前缓存JS/CSS等资源的方案外,提前缓存html页面也是业界常用的优化手段,在页面未SSR化之前,由于性能瓶颈并不在html数据下载上,这种缓存机制并未取得较好的效果,在页面SSR化之后,这种方式又进入了我们的视野,在渲染数据已经生成完毕之后,这样的缓存机制理论上能够发挥更大的作用。

但同时我们又遇到了其他困难,由于个性化算法在业务中的应用已经非常广泛,将页面提前缓存并在一定时间内保持内容不变的方式,与业务上保持页面数据实时刷新的诉求形成了冲突。这使得我们需要找到更加适合业务场景的优化的技术方案。

Android系统在做Activity页面跳转切换时会有系统耗时,这个耗时和设备性能成反比,我们在页面跳转切换的同时拦截用户点击 web 页面的行为来提前启动任务并行加载H5页面的SSR数据。然后,根据 URL 和 cookie 参数生成一个唯一的令牌。在真正走到WebView 渲染时,将 URL 重定向到缓存中。同时,使用多线程锁同步和超时机制,以进一步提高H5的加载速度。

并行加载方案的大致流程图如下:

4ed3c2f258c63871631c125918650f4c.jpeg

在完成这些优化后,我们的加载速度从3.5秒继续优化到了2.8秒左右,提升了约23%。经过上述的一系列优化措施,我们的H5加载时间从最初的平均5.5秒降低到了2.8秒左右。然而,相比于纯原生(Native)页面,这个加载速度仍然存在较大的差距,需要我们继续寻找更有效的优化手段。为了进一步提高用户体验,我们进行了各种技术尝试、并通过与其他技术团队的积极交流与合作,我们又有了新的思路。

6、容器预热

在APP启动并且主线程空闲的时候,我们可以预热WebView引擎,并构建WebView缓存池,这样就能实现预热容器的复用,从而提升WebView的加载速度。这种优化策略主要针对中高性能设备和内存较大的低性能设备。在设备空闲时,我们进行WebView容器的预热,并将预热的容器添加到缓存池中。

在我们后续的使用过程中,我们直接从WebView缓存池中获取预热的WebView容器。这样可以节省创建web容器和jscore的时间。

7、页面预渲染

在TV端H5有很多业务实时场景限制,特别是运营活动这一类有很强的时效性,这对我们的优化带来了一定的限制。但是,我们找到了一些可定制化优化的场景,如:当非会员用户在观看会员专享内容的时候,通常会有6分钟的免费试看时间,试看时间结束后会自动跳转到H5。这类场景为我们进行预渲染提供了天然的优势,在类似场景下,当开始倒计时自动触发预渲染,使得H5内容得以提前加载,实现H5的秒开效果。如下GIF图所示,上图是未进行优化的加载过程,可以看到明显的黑屏和加载过程;下图是进行了预渲染优化的结果,实现了真正的秒开。

8626bed7153dee18887d73388614e08d.gif

397e18a115667e096b1f178f635556d9.gif

在完成以上这些优化措施后,对比去年的同期的数据,我们从线上数据中看到,加载时间进一步降低,从最初的非SSR平均5.5秒、SSR场景下3.5秒降至现在的平均2秒左右,对用户体验起到了明显的改善作用。

758179ffc56722fcf2771d360a518a60.png

04

   成果

我们对端上的优化进行了AB实验。经过打散平均后的试验数据显示,我们的优化措施使得订单生成页转化率平均提升了约21%,同时支付成功率的转化也平均提升了2.4%。

dbaaf48d2b9c1fa0c83d47be3cf5877c.jpeg

518ee5b0a38e8bef00f743c32716fa14.jpeg

实验证明,提升关键业务页面的加载速度和用户体验,对业务有非常直接的正向提升作用,这也为我们后续持续推进优化提供了充足的信心和动力。

05

   未来规划

未来,我们期望通过寻找更多方法,进一步降低性能指标,将页面平均耗时控制在2秒以内,并且控制劣化。

此外,我们注意到,平均数据并不能完全反映实际的用户体验,一些尾部用户仍然面临较差的使用体验,我们将继续分析90分位值之后的用户遇到的实际情况,并进行针对性优化。同时,我们将继续针对重要的业务场景如收银台进行定制化的优化,进一步提升关键业务的加载速度,从而不断改善用户体验和提高业务转化。

a7d01f2d5d6c15b22e34cf33687f8cad.jpeg

也许你还想看

安卓TV插件化9.0内联崩溃原因及解决方案

维护几十种语言和站点,爱奇艺国际站WEB端网页优化实践

爱奇艺知识WEB前端组件化实践

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/227604.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt QAction添加图片

QAction用的时候,时常需要添加图片,如上图所示,代码如下所示: 测试的图片格式包含png,jpg,bmp,svg,其他未测试

年终跑步总结

第一个365天无间断年 以前也跑步很频繁,但今年是第一次365天未缺勤。年跑步量也是历来个人最多:2900km以上。 连续跑步天数累积超700天了 这里出现的签到天数累加只有666次,因为中间有跑步、但没有到app上签到,实际最近一次停…

RabbitMQ消息确认机制

介绍 在使用RabbitMQ发送消息如果出现消息没有发送到,队列没有接收到情况。需要消息确认来排错。 RabbitMQ发送端确认 ConfirmCallback 确认模式 和 ReturnCallback 未投递到 queue 退回模式 ConfirmCallback 确认模式 是生产者发送消息 被broker接收 会触发ConfirmCallba…

kafka实现延迟消息

背景 我们知道消息中间件mq是支持延迟消息的发送功能的,但是kafka不支持这种直接的用法,所以我们需要独立实现这个功能,以下是在kafka中实现消息延时投递功能的一种方案 kafka实现延时消息 主要的思路是增加一个检测服务,这个检…

条款 12:拷贝对象的所有部分

编译器生成的拷贝函数(拷贝构造函数,拷贝赋值运算符),会拷贝对象的所有数据,当你声明自己的拷贝函数时,就是在告诉编译器,默认实现中有你不喜欢的地方。 void logCall(const std::string& …

Apple Unity Plugins 接入GameCenter 崩溃解决方案

目录 问题问题原因解决方案可直接使用的UnityPlugins 问题 调用 GKLocalPlayer.Local.FetchItems() 程序崩溃,报错:Thread 1: EXC_BAD_ACCESS (code257, address0x8000000000000002) 启动崩溃,报错:Library not loaded: rpath/Ap…

【Electron】webview 实现网页内嵌

实现效果: 当在输入框内输入某个网址后并点击button按钮 , 该网址内容就展示到下面 踩到的坑:之前通过web技术实现 iframe 标签内嵌会出现 同源策略,同时尝试过 vue.config.ts 内配置跨域项 那样确实 是实现啦 但不知道如何动态切换 tagert …

sklearn学习的一个例子用pycharm jupyter

环境 运行在jupyter 进行开发。即一个WEB端的开发工具。能适时显示开发的输出。后缀用的是ipynb.pycharm也可以支持。但也要提示按装jupyter. 或直接用andcoda 这里我们用pycharm进行项目创建 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jupyterlab pip ins…

基于Python的电商手机数据可视化分析和推荐系统

1. 项目简介 本项目旨在通过Python技术栈对京东平台上的手机数据进行抓取、分析并构建一个简单的手机推荐系统。主要功能包括: 网络爬虫:从京东获取手机数据;数据分析:统计各厂商手机销售分布、市场占有率、价格区间和好评率&am…

Java进阶(第八期): Java中递归的的使用和递归解决一些算法问题 Java中的异常机制、异常的处理逻辑 自定义异常

文章目录 一、递归1.1 递归的介绍1.2 递归的简单练习1.3 图解递归执行流程:1.4 使用递归完成悲波那契数列1.5 猴子吃桃子问题 二、异常三 、异常的处理逻辑3.1 try catch 捕获异常3.2 throws抛出异常 四、自定义异常 Java进阶(第八期) 一、递…

科技云报道:开源才是大模型的未来?

科技云报道原创。 一年前,ChatGPT横空出世;7个多月后,Meta宣布开源LLaMA 2,并且可免费商用。 这一天,也成为大模型发展的分水岭。短时间内,LLaMA 2对一些闭源的大模型厂商造成了致命性的打击。 随后&…

SpringMVC源码解析——DispatcherServlet初始化

在Spring中,ContextLoaderListener只是辅助功能,用于创建WebApplicationContext类型的实例,而真正的逻辑实现其实是在DispatcherServlet中进行的,DispatcherServlet是实现Servlet接口的实现类。Servlet是一个JAVA编写的程序&#…

HBase 超大表迁移、备份、还原、同步演练手册:全量快照 + 实时同步(Snapshot + Replication)不停机迁移方案

博主历时三年精心创作的《大数据平台架构与原型实现:数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行,点击《重磅推荐:建大数据平台太难了!给我发个工程原型吧!》了解图书详情,…

自动化测试系列 之 Python单元测试框架unittest

一、概述 什么是单元测试 单元测试是一种软件测试方法,是测试最小的可测试单元,通常是一个函数或一个方法。 在软件开发过程中,单元测试作为一项重要的测试方法被广泛应用。 为什么需要单元测试 单元测试是软件开发中重要的一环&#xf…

TG7050CKN,TG7050SKN ,TG7050CMN,TG7050SMN

爱普生推出的温补晶振型号:TG7050CKN,TG7050SKN ,TG7050CMN,TG7050SMN频率范围为 10mhz ~ 54mhz 适用于广泛的频率需求。这几款的特点就是耐高温,温度可达105℃高温,而且都是高稳定性温补晶振,&…

21 UVM printer

uvm_printer 类提供了以不同格式打印 uvm_objects 的灵活性。我们已经讨论了使用 uvm_field_* 宏的 print() 方法,或者如果不使用 utils_begin/ end 宏,则编写 do_print() 方法。 UVM printer提供四种内置printer。 uvm_printeruvm_table_printeruvm_t…

键盘字符(#键)显示错误

当屏幕上显示的键与键盘上按下的键不同时,尤其是 # 键。大多数情况下,此错误是由于 raspbian 和 NOOBS 软件的默认英国键盘配置所致。 解决方案: 要解决此问题,您需要将配置更改为您自己的键盘或语言的配置。这可以通过转到树莓派…

EasyCVR无人机推流+人数统计AI算法,助力公共场所人群密度管控

一、背景与需求 在公共场所和大型活动的管理中,人数统计和人群密度控制是非常重要的安全问题。传统的方法可能存在效率低下或准确度不足的情况,无法满足现代社会的需求。TSINGSEE青犀可以利用无人机推流AI人流量统计算法,基于计算机视觉技术…

项目实战--Message Queue

一. 概念篇 我们在学习多线程的时候,学习过生产者-消费者模型,为了实现解耦合和削峰填谷,引入了阻塞队列. 在实际的后端开发中,跨主机之间使用生产者消费者模型,也是非常普遍的需求,因此,阻塞队列会被封装成一个独立的服务器程序,实现更丰富的功能.这样的程序称为"消息队列…

Spark编程实验四:Spark Streaming编程

目录 一、目的与要求 二、实验内容 三、实验步骤 1、利用Spark Streaming对三种类型的基本数据源的数据进行处理 2、利用Spark Streaming对Kafka高级数据源的数据进行处理 3、完成DStream的两种有状态转换操作 4、把DStream的数据输出保存到文本文件或MySQL数据库中 四…