专栏首页code秘密花园逐帧分析youtube

逐帧分析youtube

接下来我会逐个请求分析youtube究竟使用那些国内大家不那么常用的技术,因为点会比较多我在正文中就不一一详细介绍了但都会配上相关阅读连接,我只会对与带来关键性能提升的部分做展开分析。

  • Part1 网络请求分析
  • Part2 使用技术分析
  • Part3 性能分析

Part1 网络请求

协议

http/2 + quic/46

从截图可见youtube在html文档和静态资源请求上都启用了http/2 + quic/46,http/2相信还有比较多人已经开始尝试使用了,但quic在生产环境使用的并不多见。QUIC(Quick UDP Internet Connection)是google自spdy后推出的新的协议,从名字就能看到它最大的区别是使用UDP传输协议,这可以说是对http/2是一个关键的补充,因为在现实世界中我们会遇到http/2队头阻塞问题,在丢包比较严重的环境下http/2的性能是会有所下降的,而在网页这种多请求并发的情况下由于http/2的多路复用(同一个域名下共享一个tcp)的情况下http/2的整体性能甚至会比http1.1更差,而quic在解决了tcp的队头阻塞的同时实现了0RTT数据传输,连接迁移等新特性。

用最直观的感受来解释就是使用quic后网站的性能提升15%,弱网环境提升20%,如果你的用户会频繁的wifi 4g之间切换或者经常乘坐高铁、地铁高速移动,quic让他们ip变更时不要重新建联,这对视频网站来说是非常有意义的提升。

cnblogs.com/jb2011/p/84

52im.net/thread-1309-1-

html http header

Referrer Policy

  • 首页 :no-referrer-when-downgrade (浏览器默认)
  • 播放页:origin-when-cross-origin

首页的设置是浏览器默认设置我们就不需要讨论了,但播放页的设置不同origin-when-cross-origin的目标是保护隐私,因为播放页是带参数的,为了避免被下一跳的第三方页面知道用户是从哪个视频内容发生的跳转所以只返回host信息

developer.mozilla.org/z

alt-svc: quic=":443"; ma=2592000; v="46,44,43,39"

alt-svc的全名是HTTP Alternative Services,服务端可以将自己的替代服务地址以协议规定的方式告诉浏览器,对于支持这个协议的浏览器来说,后续请求都会使用新地址。除了提供替代服务外,理论上我们还能通过这个字段的设置来引导用户访问不同的多语言版本或者abtest版本哦。

imququ.com/post/http-al

content-encoding: br

与常见的通用压缩算法不同,br(Brotli)使用一个预定义的120千字节字典。该字典包含超过13000个常用单词、短语和其他子字符串,这些来自一个文本和HTML文档的大型语料库。

zh.wikipedia.org/wiki/B

tools.ietf.org/html/rfc (你是不是很好奇这120千字节的字典里有什么?)

strict-transport-security: max-age=31536000

通常简称为HSTS是一个安全功能,它告诉浏览器只能通过HTTPS访问当前资源,而不是HTTP。

developer.mozilla.org/z

x-content-type-options | x-frame-options | x-xss-protection

安全响应头

imququ.com/post/web-sec

JS http header

timing-allow-origin: https://www.youtube.com

允许哪个域名可以访问当前资源的Resource Timing API提供的相关信息。

developer.mozilla.org/z

html http header

我们可以看到第五个请求是一个html文档,它是通过一个比较有趣的方式引入到页面当中的:import html

https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/HTML导入 已不建议使用

CSS http header

link: https://fonts.gstatic.com; rel=preconnect; crossorigin

css请求header中完成预连接算是相对少见的做法,但在css内部引用了较多非当前域名资源的情况下在http header里声明预连接会比在当前页面或前置页面用通过<link perconnect>要更通用一些,因为你不需要考虑前置页面都有哪些。

w3.org/TR/resource-hint

cdnplanet.com/blog/fast

IMG http header

access-control-expose-headers: Content-Length

允许访问Content-Length,应该是为了做客户端资源加载速度的分析而提供的信息。

developer.mozilla.org/z

content-disposition: inline;filename="unnamed.jpg"

inline声明图片应该被行内显示而不是作为附件下载,filename是下载时使用的默认名称

rfc-editor.org/rfc/rfc1

AJAX http header

P3P:个人隐私安全平台项目(The Platform forPrivacy Preferences Project)的标准

  • p3p: policyref="googleadservices.com/pa", CP="xxxxxx"
  • p3p: CP="This is not a P3P policy! See support.google.com/acco for more info."

https://zh.wikipedia.org/zh-hans/隱私權偏好平台

Part2 使用技术介绍

Web Animations api

允许同步和定时更改网页的呈现, 即DOM元素的动画。它通过组合两个模型来实现:时序模型 和 动画模型。

developer.mozilla.org/z (api介绍)

github.com/web-animatio (实现)

github.com/web-animatio (polyfill)

Web Components & Polymer

允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的web应用中使用它们。

developer.mozilla.org/z

github.com/webcomponent

polymer-zh.cn/

requestIdleCallback & cancelIdleCallback

会在浏览器空闲时期依次调用函数, 这就可以让开发者在主事件循环中执行后台或低优先级的任务,而且不会对像动画和用户交互这样延迟敏感的事件产生影响。函数一般会按先进先调用的顺序执行,然而,如果回调函数指定了执行超时时间timeout,则有可能为了在超时前执行函数而打乱执行顺序。

developer.mozilla.org/z

developer.mozilla.org/z

SPF.js

一个轻量级的JS框架,用于把youtube改造为一个单页应用。

SPF

normal

youtube.github.io/spfjs

github.com/youtube/spfj

youtube.com/watch?

在一次页面跳转的过程:<a href = "feed/trending"> 为普通连接,点击后被network.js劫持后发出为feed/trending?pbj=1的请求

在返回头中有如此信息:x-spf-response-type:multipart

返回的正文从html变成了一个json对象,包含了渲染对应模块所需的数据。

同类实现算是比较多的,facebook早年的bigpipe,微博都有使用类似的技术减少连续访问时相同模块的重复渲染浪费。

Part3 性能分析

上面科普了挺多的技术点,或多或少都跟性能有些关系。这部分请跟随我的视角来看看性能方面youtube还做了哪些优化。

内联脚本与CSS

查看页面源代码我们可以看到youtube的html是做了SSR的,但并没有做data→dom的这一步,因此当中不仅有模块初始化的JS、CSS代码外,还有包含关键数据的JSON。观察下来youtube页面基本遵循了一个规律,有共性需要的js、css才做外联,当前页面所必须的js与css做内联。可能一部分同学会质疑这个做法与曾经的优化建议里说的不一样,经过B站自己的实验证明,在html文件体积可控的情况下把页面必须的js、css内联,首屏的渲染速度会有较大的提升,其收益主要来自减少了http建联的时间。在用户真实的使用场景当中,每有一个请求在播放器初始化之前,哪怕是一个http204的请求都会对我们视频首帧播放的8分位时间有50-100ms的影响。

另外,我们还发现一点是youtube对播放的依赖进行了较好的治理,大家可以尝试把红框内的所有请求都block掉,再刷新页面

你会神奇的发现,虽然样式有一些错乱,播放器意外的模块加载失败,但播放器与视频依然保持正常运作。虽然这不是正常用户的行为,但能做到这一点并关联上文中提到的requestIdleCallback & cancelIdleCallback的空闲时执行的调度能力,我们知道虽然这些脚本的加载在播放器之前,但是他们的执行时机完全可以被后置,最终实现播放器的优先渲染。

从连续截图中我们也可以印证这一点

如果我们对xhr等数据请求做同样的处理,我们还能印证另外一点,就是首屏渲染的所有数据都已经在SSR中提供了,不需要额外的请求接口。

SVG代替icon

从页面源代码我们还能看到另外一点是youtube的icon全都是用svg实现的,这是和他们采取的扁平化的设计是分不开的,而内联的svg不仅仅带来了体积小、连接数少的好处,如果你仔细观察你还会看到大部分的icon都是有小动效的,这些动效是依靠svg动画实现的,比传统的gif或者序列帧动画体积可要小太多了。

SPA

youtube的设计几经修改后最后固化为当前我们熟悉的版本,在不同的页面跳转过程中顶部和侧边栏菜单是作为常驻模块存在,只需要渲染右侧的content。对于大多前端来说新做一个spa项目是相对容易的,而对于youtube这个庞大的网站而言通过重构把多页面重构为单页面的代价远大于收益,因此他们是通过spf.js框架来解决这个问题的,劫持全局A链接的点击事件,只请求下一个页面渲染所需的数据在当前页面完成渲染,避免了大量无意义的http建联和模块重新渲染的开销,加快了页面渲染的速度。

而在视频连续播放的场景中,播放器的初始化也是一个巨大的开销往往要需要400-600ms来完成,在spf.js的加持下播放器不需要重新初始化只需要载入下一个视频的数据即可。如果你觉得体验youtube比较困难的话,你可以来b站试试,访问右侧的相关推荐我们同样重用了页面和播放器,此时从点击卡片到视频能够播放只需要500ms不到的时间。

跨页面缓存

无缓存访问

有缓存访问

通过上图可以看到youtube的静态资源是有冗余部分的而且体积相当的大(300k的js 600k的import html),并没有按页面维度进行最小化的打包,这应该是为了做成spa后下一个页面的渲染不需要请求更多的资源即可完成,从单个页面加载速度来看这显然是不划算的,不知道youtube是不是经过自己的实验证明了在用户连续访问的场景中这样做的整体收益更大呢?

WebM/vp9 → AV1

视频网站的关键速度是首帧时间,影响这个时间的除了我们前面分析的页面加载顺序和资源优化外,很重要一点就是视频格式,而这当中youtube的魔法是真的多。在youtube的分享中我们可以看到目前youtube主要使用的是vp9,它只需要h.264一半的体积就能提供相同的画质

youtube.com/watch?

另一项魔法如上图,我们可以看到一帧画面被分割成了不同尺寸的格子,youtube对此进行了自动量化的实验,目的是对于视觉敏感的区域输出更多的细节,对于不敏感的区域降低细节。

vp9的窄带高清的能力,在全球范围内为youtube带来了非常可观的增长。在你可能因为vp9感到兴奋时,youtube去年在vp9的基础上又再推出了av1,av1比vp9体积又减少了30%。

未来在移动设备上还有会有原生支持。

末尾

我们来回顾一下从分析youtube代码我们得到了哪些优化建议:

  1. 协议层面尽快升级到http/2+quic(http/3),会为我们带来15%性能提升,并且可以让挤地铁的同学有更好的视频播放体验。
  2. 压缩格式br,可以更有效的压缩html、js、css
  3. 对于多页面公用的css和js,你可以通过在http header中增加link perconnent,让文件内引用的其他域名获得加速,而不需要在html新增标签覆盖面更广
  4. 合理使用requestIdleCallback & cancelIdleCallback可以让你的代码执行减少拥堵。
  5. 如果你需要把一个多页面站点改造成单页应用又不想付出高昂的代价,可以尝试考虑spf.js的方案(但需要服务端配合哦!)
  6. 在首个请求体积可控的情况下内联必须的JS和CSS会让你获得更快的首屏时间(根据我们实验结果建议<200k)
  7. 采用svg实现icon,不仅体积小还可以实现动画,比base64和iconfont要更灵活。(需要设计配合)
  8. 尽可能能的重用页面资源和已渲染的模块,避免任何一点不必要的浪费。
  9. vp9和av1比国内常见的h.264有明显的优势,而且不像h.265要收取高额的费用。

最后补充一点:Node ssr是好东西,有了它前面几点才能在团队的闭环里完成不需要求人。

本文分享自微信公众号 - code秘密花园(code_mmhy)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 前端技术观察第 20 期

    https://mobiledevweekly.com/link/90084/web

    ConardLi
  • 移动端体验优化经验总结与实践

    很多企业都会特别注重自己产品的体验,尤其是移动端,那移动端的体验为什么这么重要?首先体验本身就很重要,好的体验带给用户的感受是截然不同的,用户选择使用一个产品除...

    ConardLi
  • 前端技术观察第 15 期

    ConardLi
  • 两个有趣的统计学问题

    今天在学习统计学的时候,碰到了一个很有趣的统计学问题。这个场景是如何统计大学生中考试作弊的比例,假设样本是100个学生。

    jeanron100
  • Google Home创始团队成员空降物灵星舰,相约“Ling Talk”一起聊聊智能音箱那些事儿

    今天的孩子们被叫做“触摸一代”,他们潜意识里,会认为所有的平面都是像iPad一样可以通过点击、拖拽等动作而产生交互的。(虽然物灵对此并不认可,并且也在尽力做着将...

    企鹅号小编
  • RecyclerView 实现横向滚动效果

    我相信很久以前,大家在谈横向图片轮播是时候,优先会选择具有HorizontalScrollView效果和ViewPager来做,不过自从Google大会之后,系...

    xiangzhihong
  • 整合SSM

    我们整合SSM框架,其实就是用Spring去整理其余二者,主要以Spring为主。其工作流程是Web层调用Service层,而Service层调用Dao层,那么...

    晚上没宵夜
  • 并发基石-AQS与Condition

    在前面的博客JUC相关中,已经初略介绍了Condition接口,代表一个条件,可以阻塞、唤醒一个条件队列 今天来具体讲讲其与AQS(AbstractQueueS...

    歪歪梯
  • 如何优雅地链式取值

    但是对于这种操作报出类似于Uncaught TypeError: Cannot read property 'goods' of undefined 这种错误也...

    用户1515472
  • 【DB笔试面试813】在Oracle中,什么是闪回删除(Flashback DROP)?回收站的作用是什么?​

    【DB笔试面试813】在Oracle中,什么是闪回删除(Flashback DROP)?回收站的作用是什么?

    小麦苗DBA宝典

扫码关注云+社区

领取腾讯云代金券