作者 | 任雪龙
导读
网络直播功用作为一项互联网基本才干现已越来越重要,手机中的直播功用也越来越完善,电商直播、新闻直播、文娱直播等多种直播类型为用户供给了丰富的直播内容。跟着直播的普及,为用户供给极速、流畅的直播观看体会也越来越重要。
全文6657字,预计阅读时刻17分钟。
01 布景
百度 APP 作为百度的航母级应用为用户供给了完善的移动端服务,直播也作为其间一个必要功用为用户供给内容。跟着直播间架构、事务才干逐步老练,直播间播映方针优化也越来越重要。用户点击直播资源时,能够快速的看到直播画面是其间一个中心体会,起播速度也就成了直播间优化中的一个要害方针。
02 现状
因为包体积等原因,百度 APP 的 Android 版中直播功用运用插件方法接入,在用户真实运用直播功用时才会将直播模块加载。为处理用户点击直播功用时需求等候插件下载、装置、加载等阶段及兼容插件下载失利的状况,直播团队将播映、IM 等中心才干抽到了一个独立的体积较小的一级插件并内置在百度 APP 中,直播间的挂件、礼物、重视、点赞等事务才干在另外一个体积较大的二级插件中。特别的插件逻辑和杂乱的事务场景使得 Android 版全体起播时长方针表现的不尽人意。
2022 年 Q1 直播间全体起播时长方针 80 分位在 3s 左右,其间二跳(直播间内上下滑)场景在 1s 左右,插件拆分上线后通过调查起播数据发现跟着版别收敛,一跳进入直播间带着流地址(页面发动后会运用该地址预起播,与直播列表加载同步履行)场景起播时有显着的增长,从发版别初期 1.5s 左右,随版别收敛两周内会逐步增长到 2.5s+。也便是线上在直播间外点击直播资源进直播间时有很大一部分用户在点击后还需求等候 3s 乃至更长时刻才干真实看到直播画面。这个时长对用户运用直播功用有十分大的负向影响,起播时长方针急需优化。
03 方针
△起播链路
起播进程简略描绘便是用户点击直播资源,翻开直播页面,恳求起播地址,调用内核起播,内核起播完结,内核告诉事务,事务起播完结打点。从对内核起播时长监控来看,直播资源的在内核中起播耗时大约为 600-700ms,考虑链路中其他阶段损耗以及二跳(直播间内上下滑)场景能够在滑动时提早起播,全体起播时长方针定位为1.5 秒;考虑到有些进入直播间的方位现已有了起播流地址,能够在某些场景省去 “恳求起播地址” 这一个阶段,在这种直播间外现已获取到起播地址场景,起播时长方针定为 1.1 秒。
04 难点
特别的插件逻辑和杂乱的事务场景使得 Android 版每一次进入直播的起播链路都不会彻底一样。只有一级插件且二级插件还未安排妥当时在一级插件中恳求直播数据并起播,一二级插件都已加载时运用二级插件恳求直播数据并处理起播,进直播间带着流地址时为完结秒开在 Activity 发动后就创立播映器运用直播间外带着的流地址起播。除了这几种链路,还有一些其他状况。杂乱的起播链路就导致了,尽管在起播进程中首要节点间都有时刻戳打点,也有天等级相邻两个节点耗时 80 分位报表,但线上不同场景上报的起播链路无法穷举,运用现有报表无法剖析直播大盘起播链路中真实耗时方位。需求建立新的监控计划,找到耗时点,才干规划针对性计划将各个耗时方位进行优化。
05 处理计划
5.1 规划新报表,定位耗时点
△一跳有起播地址时起播链路简图
因为现有报表无法满足起播链路耗时阶段定位,需求规划新的监控计划。调查在翻开直播间时有流地址场景的流程图(上图),进入直播间后就会同步创立直播间列表及创立播映器预起播,当直播间列表创立完毕且播映器收到首帧告诉时起播流程完毕。尽管用户点击到页面 Activity 的 onCreate 中可能有多个节点(一级插件装置、加载等),页面 onCreate 调用播映器预起播中可能多个节点,内核完结到直播事务收到告诉中有多个节点,导致整个起播链路无法穷举。可是咱们能够发现,从用户点击到 onCreate 这个途径是肯定会有的,onCreate 到创立播映器途径也是肯定有的。这样就阐明尽管两个要害节点间的节点数量和链路无法确认,可是两个要害节点的先后顺序是一定的,也是必定会有的。由此,咱们能够规划一个自定义链路起点和自定义链路终点的查询报表,通过终点和起点时刻戳求差得到两个任意节点间耗时,将线上这两个节点一切差值求 80 分位,就能够得到线上起播耗时中这两个节点间耗时。将起播链路中一切中心要害节点计算耗时,就能够找到整个起播链路中有反常耗时的分段。
按照上面的思路开发新报表后,上面的链路各阶段耗时也就比较明晰了,见下图,这样咱们就能够针对不同阶段逐个击破。
△要害节点间耗时
5.2 一跳运用一级插件起播
运用新报表计算的要点节点间耗时调查到,直播间列表创立(模版组件创立)到真实调用起播(事务视图安排妥当)中心耗时较长,且这个耗时跟着版别收敛会逐步添加,两周内大约添加 1000ms,首先咱们处理这两个节点间耗时添加问题。
通过起播链路调查和剖析后,发现随版别收敛,这部分起播链路有较大改变,首要是因为随版别收敛,在二级插件中触发 “事务调用起播” 这个节点的占比添加。版别收敛期,进入直播间时大概率二级插件还未下载安排妥当或未装置,此刻一级插件中能够很快的进行列表创立并创立事务视图,一级插件中在 RecyclerView 的 item attach 到视图树时就会触发起播,这个链路首要是等候内核完结首帧数据的拉取和解析。当二级插件逐步收敛,进入直播间后一级插件就不再创立事务视图,而是有二级插件创立事务视图。因为二级插件中事务组件较多逐个加载需求耗时还有一级到二级中逐层调用或事情分发也存在一定耗时,这样二级插件起播场景就大大添加了直播间列表创立(模版组件创立)到真实调用起播(事务视图安排妥当)中心耗时。
5.2.1 一跳悉数运用一级插件起播
根据上面的问题剖析,咱们修改了一跳场景起播逻辑,一跳悉数运用一级插件起播。一级插件和二级插件创立的播映器父容器 id 是相同的,这样在一级插件中初始化播映器父容器后,当内核首帧回调时起播进程就能够完毕了。二级插件中在初始化播映器父容器时也会通过 id 判别是否现已添加到视图树,只有在未添加的状况(二跳场景或一跳时出现反常)才会在二级中进行兜底处理。在一级插件中处理时速度能够更快,一级优先二级兜底逻辑保证了进入直播间后一定能够顺畅初始化视图。
5.2.2 提早恳求接口
运用由一同插件处理起播优化了二级插件链路层级较多问题,还有一个耗时点便是进直播间时只传入了房间 room_id 未带着流地址场景,此刻需求通过接口恳求获取起播数据后才干创立播映器和起播。为优化这部分耗时,咱们规划了一个直播间数据恳求管理器,供给了缓存数据和超时整理逻辑。在页面 onCreate 时就会触发管理器进行接口恳求,直播间模版创立完结后会通过管理器获取现已恳求到的直播数据,假如管理器接口恳求还未完毕,则会复用进行中恳求,待恳求完毕后立刻回来数据。这样在进直播间未带着流数据时咱们能够充分利用图中这 300ms 时刻做更多必要的逻辑。
5.3 播映器Activity外预起播
通过进直播间播映器预创立、预起播、一跳运用一级插件起播等计划来优化进入直播间事务链路耗时后,事务链路耗时逐步低于内核部分耗时,播映器内核耗时逐步成为一跳起播耗时优化瓶颈。除了在内核内部探索优化计划,继续优化事务整个起播链路也是一个重要方向。通过节点间耗时能够发现,用户点击到 Activity 页面 onCrete 中心也是有 300ms 左右耗时的。当无法将这部分耗时缩到更短时,咱们能够测验在这段时刻并行处理一些工作,减少页面发动后的部分逻辑。
一级插件在百度 APP 中内置后,规划并上线了插件预加载功用,上线后用户通过点击直播资源进入直播间的场景中,有 99%+ 占比都是直播一级插件已加载状况,一级插件加载这儿就没有了更多能够的操作空间。但将预起播机遇提早到用户点击处,能够将内核数据加载和直播间发动更大程度并行,这样来下降内核耗时对整个起播耗时影响。 △播映器在直播间外起播示意图
如上图,新增一个提早起播模块,在用户点击后与页面发动并行创立播映器起播并缓存,页面发动后创立播映器时会先从提早起播模块的缓存中测验取已起播播映器,假如未获取到则走正常播映器创立起播逻辑,假如获取到缓存的播映器且播映器未产生错误,则只需求等候内核首帧即可。
播映器提早起播后首帧事情大概率在 Activity 发动后到达,但仍有几率会早于直播事务中设置首帧监听前到达,所以在直播间中运用复用内核的播映器时需求判别是否起播成功,假如现已起播成功需求立刻分发已起播成功事情(含义差异于首帧事情,防止与首帧事情混淆)。
提早起播模块中还规划了超时回收逻辑,假如提早起播失利或 5s (暂定)内没有被事务复用(Activity 发动反常或其他事务反常),则自动回收缓存的播映器,防止直播间没有复用成功时提早创立的播映器占用较多内存及防止泄漏;超时时刻是根据线上大盘起播时刻决定,运用一个较大盘起播时刻 80 分位稍高的值,防止起播还未完结时被回收,但也不能设置较长,防止不会被复用时内存占用较多。
通过提早起播功用,实验期射中提早起播逻辑较不进行提早起播逻辑,全体起播耗时 80 分位优化均值:450ms+。
5.4直播间使命打散
△内核首帧分发耗时
事务链路和内核链路耗时都有一定优化后,咱们继续拆解要点节点间耗时。内核内部符号首帧告诉到直播事务真实收到首帧告诉之间耗时较长,如上图,线上内核首帧分发耗时 80 分位均值超越 1s,该分段对全体起播耗时优化影响较大。内核首帧是在子线程进行符号,告诉事务时会通过主线程 Handler 分发音讯,通过系统的音讯分发机制将事情转到主线程。
通过排查内核符号首帧时刻点到事务收到首帧告诉事情时刻点之间一切主线程使命,发现在首帧分发使命开始排队时,主线程使命行列中已有较多其他使命,其他事情处理时刻较长,导致首帧分发排队时刻较久,分发使命全体耗时也就较长。直播事务杂乱度较高,假如内核首帧分发使命排队时直播间其他使命已在行列中或正在履行,首帧分发使命需求等直播使命履行完结后才干履行。
通过将直播间发动进程中一切主线程使命进行筛查,发现二级插件的中事务功用较多,全体加载使命履行时刻较长,为验证线上也是因为二级事务使命堵塞了首帧分发使命,咱们规划了一个二级组件加载需求等候内核首帧后才干进行的实验,通过实验组与对照组数据比照,在射中实验时首帧分发耗时和起播全体耗时悉数都有显着下降,全体耗时有 500ms 左右优化。
通过实验验证及本地对起播阶段事务逻辑剖析,定位到直播间各事务组件及对应视图的预加载数量较多且耗时比较显着,这个功用是二级插件为充分利用直播间接口数据回来前时刻,二级插件加载后会与接口恳求并行提早创立事务视图,提起初始化组件及视图为接口完结后组件烘托节省时刻。假如不预创立,接口数据回来后初始化事务组件也会自动创立后设置数据。但将一切预创立使命悉数串行履行耗时较长,会堵塞主线程,页面一帧中履行太多使命,也会形成页面显着卡顿。
发现这个堵塞问题后,咱们规划了将预创立视图使命进行拆分打散,将一同履行的大使命拆分成多个小使命,每个组件的初始化都作为一个独自使命在主线程使命行列中进行排队等候履行。防止了一个大使命耗时特别长的问题。该功用上线后,整个二级插件中的组件加载大使命耗时下降了 40%+。
5.5 内核子线程分发首帧
因为主线程音讯行列中使命是排队履行的,将堵塞首帧分发事情的大使命拆分成较多小使命后,仍是无法处理首帧事情开始排队时这些小使命现已在主线程使命行列中排队问题。除了下降直播事务影响,还能够通过加快内核使命分发速度,使首帧分发耗时下降。需求规划一个在不影响内核稳定性与事务逻辑状况下内核首帧事情如何防止主线程排队或快速排队后被履行的计划。
为处理上面的问题, 咱们推动内核,独自添加了一个子线程告诉事务首帧事情才干。事务收到子线程中首帧回调后通过 Handler 的 postAtFrontOfQueue() 方法将一个新使命插到主线程使命行列最前面,这样主线程处理完当前使命后就能够立刻处理咱们新建的这个使命,在这个新使射中能够立刻处理播映器上屏逻辑。无需等候播映内核原本的主线程音讯。
主线程使命前插无法打断新使命排队时主线程中现已开始履行的使命,需求正在履行使命完毕后才会被履行。为优化这个场景,内核通过子线程告诉首帧后,播映器中需求记载这个状况,在一级插件及二级插件中的直播间事务使命履行开始前后,添加判别播映器中是否现已收到首帧逻辑,假如现已收到,就能够先处理上屏后再继续当前使命。
通过直播内核首帧音讯在主线程使命行列前插和事务要害节点添加是否可上屏判别,就能够较快处理首帧告诉,下降首帧分发对起播时长影响。
5.6 起播与完载方针平衡
直播间起播优化进程中,完载时长方针(完载时长:用户点击到直播间中心功用悉数出现的时刻,其间阅历页面发动,直播间列表创立,二级插件下载、装置、加载,直播间接口数据恳求,初始化直播间功用组件视图及烘托数据,中心事务组件显示等阶段)的优化也在继续进行。直播间二级插件是在运用二级插件中的功用时才会触发下载装置及加载逻辑,完载链路中也注意到了用户点击到页面 onCreate 这段耗时,见下图。
△页面发动耗时示意图
为优化直播间完载方针,直播团队考虑假如将插件加载与页面发动并行,那么完载耗时也会有一定的优化。直播团队继续规划了二级插件预加载计划,将二级插件加载方位提早到了用户点击的时分(该功用上线在 5.4、5.5 章节对应功用前)。该功用上线后实验组与对照组数据显示,实验组完载耗时较对照组确实有 300ms+ 优化。但起播耗时却出现了反常,实验组的起播耗时显着比对照组增长了 500ms+,且随版别收敛这个起播劣化还在添加。咱们立刻很快发现了这个反常,并通过数据剖析确认了这个数据是正确的。完载的优化时如何引起起播改变的?
通过数据剖析,咱们发现起播受影响的首要方位仍是内核首帧音讯分发到主线程这个分段引起,也便是二级插件加载越早,内核首帧分发与二级组件加载时的耗时使命抵触可能性越大。确认问题原因后,咱们做了 5.4、5.5 章节的功用来下降二级组件加载使命对起播影响。因为二级插件中的耗时使命彻底拆分打散来缓解二级插件预下载带来的起播劣化计划杂乱度较高,对直播间逻辑侵入太大,二级插件提早加载没有彻底上线,完载的优化咱们规划了其他计划来完结方针。
尽管不能在进入直播间时直接加载二级插件,但咱们能够在进入直播间前尽量将二级插件下载下来,运用时直接加载即可,这个耗时相对下载耗时是十分小的。咱们优化了插件预下载模块,在直播间外展现直播资源时触发该模块预下载插件。该模块会通过对当前设备网络、带宽、下载频次等条件归纳判别,在合适的机遇将匹配的二级插件进行下载,插件提早下载后对完载方针有较大优化。除了插件预下载,直播间内通过 5.4 章节直播间二级组件初始化拆分,也将悉数组件初始化对主线程堵塞进行了优化,这样接口数据恳求成功后能够优先处理影响完载计算的组件,其他组件能够在完载完毕后再进行初始化,这个计划也对直播完载方针有显着优化。
除了以上两个优化计划,直播团队还在其他多个方向对完载方针进行了优化,同时也处理了完载时长与起播时长的方针平衡,没有因为一个方针优化而对其他方针形成劣化影响。最终完结了起播、完载方针悉数到达方针。
06 收益
△2022 Android 端起播耗时走势
通过以上多个优化计划逐步迭代,现在 Android 端最新版别数据,大盘起播时刻现已由 3s+ 降到 1.3s 左右;一跳带流地址时起播时长由 2.5s+ 左右下降到 1s 以内;二跳起播时长由 1s+ 下降到 700ms 以内,成功完结了预订方针。
07 展望
起播时长作为直播功用一个中心方针,还需求不断打磨和优化。除了事务架构上的优化,还有优化拉流协议、优化缓冲装备、自适应网速起播、优化 gop 装备、边际节点加快等多个方向能够探索。百度直播团队也会继续深耕直播技能,为用户带来越来越好的直播体会。
——END——
推荐阅读:
iOS SIGKILL 信号量崩溃抓取以及优化实践
如何在几百万qps的网关服务中完结灵活调度战略
浅显易懂DDD编程
百度APP iOS端内存优化实践-内存管控计划
Ernie-SimCSE比照学习在内容反作弊上应用
质量评估模型助力风险决策水平提升