写点什么

借助性能优化促进用户数增长

2017 年 4 月 18 日

2015 年上半年,Pinterest 的工程师进行了一次实验,借此将移动 Web 首页的页面加载性能提升了 60%,同时移动注册转化率提升了 40%。然而该实验使用了一种极为烦琐的解决方案,用到了大量“抄近道”的方法,例如提供预先生成的 HTML 页面,而没有使用内部模版渲染引擎或其他通用资源(JS、CSS)。为了将实验学到的经验实用化,整个前端引擎、所有页面模版,以及通用元素都必须重写。这是一项繁重的工作,为此我们首先需要构建一个强壮的指标,对整个系统各方面的实现进度进行追踪。本文中我们将介绍提高 Pinterest 页面性能的具体方法,以及这种方法如何在 2016 年帮助我们实现了用户数量的最大化增长。

衡量

首先我们希望明确定义并实现我们希望改进的指标。2015 年的实验中使用的指标只是从整体上衡量页面加载时间(PLT),这是指自从用户输入 URL 或点击一个 URL 后,整个页面渲染完成所需的时间。在浏览器导航时限 API 方面,navigationStart 和 domComplete 事件之间是存在时间差的:

  • navigationStart 事件是由用户点击链接或在浏览器导航栏输入 URL 并按下回车后发起的。
  • domComplete 事件是指页面上所有元素的处理工作均已完成,所有资源(例如图片、CSS、JS)均已完成下载。此时用户将不再看到浏览器标签页上旋转的图标,而页面上需要显示的其他新的内容(例如 onLoad javascript)将在此时开始执行。

(点击放大图像)

Copyright ? 17 December 2012 World Wide Web Consortium , (MIT, ERCIM, Keio, Beihang)

这个指标是个很好的起点,然而有一个重大的不足:无法反映出真实性能。这一点对用户很重要,因为页面上可见部分的加载速度要远远快于整个页面的加载速度。

用户察觉到的等待时间

为了解决这个问题,我们引入了另一个指标:用户察觉到的等待时间(UPWT),这是指从用户输入 URL 或点击 URL 后,页面上对用户可见的部分渲染完成所需的时间。这是一种基于图片加载事件的自定义指标。我们会追踪屏幕上包含的图片,以及这些图片完成加载的时间。UPWT 始于 navigationStart 事件,终于 domLoading 和 domComplete 事件之间的某一刻:

  • domLoading 事件是指浏览器接收到整个文档并开始渲染的时候。

(点击放大图像)

Copyright ? 17 December 2012 World Wide Web Consortium , (MIT, ERCIM, Keio, Beihang)

作为一种额外的收益,还可以为移动应用程序引入类似的指标,并用相同的方式进行衡量。

我们将这两个指标(整体 PLT 和 UPWT)以及其他一些性能指标(例如服务器端性能,以及更详细的浏览器端性能)结合在一起,包含在公司最重要的仪表板和我们的实验框架中。借此可以追踪进度并快速了解哪些改进可以实现最大的收获。

经验:创建追踪进度所需的正确指标,优先侧重于可以获得最大改进的指标。

优化

可优化的领域分为三个主要类别:前端、网络,以及后端。

前端

页面重量(CSS/JS/Images/HTML)

通过查看汇总后的测试结果,我们很快意识到页面加载需要极大的带宽。对于某些网络基础设施老旧的国际市场,这个问题尤为严重。为此我们对需要加载的内容进行了更细致的划分。以前我们通常会直接获取整个站点所需的 CSS 和 JS,现在,我们只获取渲染屏幕上内容所必需的 CSS 和 JS,并在初始渲染完成后再延迟加载其他资源。此外我们还研究了所请求的图片,并研究了这些图片是否都是必须的,以及能否请求尺寸经过了优化的图片。这两项措施配合使用后,展示一个页面所需下载的数据量减少了 60%。

渲染(React)

在关注性能的同时,我们还将网站端从自行开发的框架迁移到 React 。我们团队是 Pinterest 内部较早采用 React 的,这个渲染模型还让我们进一步大幅改善了性能。通过使用 React 框架我们获得了大量收益,从一种不受控制,任何东西都可以修改 DOM 的模式,转变为 React 的影子 DOM 批量更新模式。

提前进行 Flush/chunked 传输编码

为了优化客户端和服务器之间的路径,我们调查了服务器端的页面渲染方式。借此可消除不必要的缓冲,确保浏览器可以提前收到页面的部分,并立刻开始在获取数据的同时,并行获取框架级的 JS 和 CSS 资源以及进行服务器端的渲染。在渲染完成后,我们已经开始使用 Chunked 传输编码方式发送页面内容,但在仔细检查过渲染页面的服务以及最终用户之间的基础架构后,我们发现其中有好几个步骤对响应进行了缓冲,而非直接流式传输。取消缓冲后数据可以更快速到达浏览器,同时页面加载时间进一步获得了改进。

传输

CDN/DSA

我们还对传输基础架构进行了大量改进。我们在 CDN 中设置了多层缓存,启用了 IPv6,切换至 CDN 的更高服务层,同时在全球范围内引入了 SSL 边缘终结(DSA)。

后端

尽可能并行处理

页面的渲染通常需要从不同来源请求大量数据。对我们来说,则是需要进行多次 API 调用。这些调用之间存在一种很自然的数据依赖性图表,借此可以知道哪些调用可以并行处理,哪些因为数据之间的依赖性必须按顺序处理。我们开始考虑使用 GraphQL,该技术可以自动优化数据的并行获取。与此同时,我们还对当前使用的调用图表进行细致的审查,以确保所有对顺序无要求的调用都已并行处理。

只返回需要的内容

我们还对所请求的数据进行了修剪,只返回界面所必须的数据。这样不仅可以降低网络负担,而且避免了服务器端不必要的数据获取操作,因为额外的内容通常需要对后端服务进行额外的调用。

尽可能缓存一切

我们还花了一些时间将使用数据“边缘”缓存的页面类型扩展到低基数(Cardinality)页面(例如页面数量约为几百上千,而非数十亿的页面)。缓存方面还有待进一步完善,从考虑到页面数量太多,为了顾及缓存的效率而只缓存页面的“头部”数据到触发缓存在后台自动刷新等,还有很多方面有待改善。

通过改善性能实现用户数量的最大化增长

在为了改善性能而重写页面的时候,绝对不能考虑尝试新的设计。如果用其他更快速的页面设计和最初的页面进行比较,就无法知道转化率的变化到底是来自性能的改进还是设计方面的改进。我们需要构建完全相同的页面来对比。此外为了充分理解对网页性能的影响,整个实验在设置上应该能衡量不同类型页面的指标,以及分别衡量 Web 和移动 Web 的指标。随着性能的改善,不同页面会实现不同的转化率和流量收益。对我们来说,将所有页面汇总在一起查看整体转化率是不够的,我们希望能分别查看不同的转化率,随后发现桌面端 Web 转化率增加了很多,但同时移动 Web 转化率实际降低了,平均值其实是降低的。我们进一步研究了为什么移动 Web 转化率降低,并发现在功能方面存在一些问题。

为了让整体页面改进幅度最大化,还需要非常注意,就算与转化率有关的微不足道的功能也需要重新实现。我们最初的页面包含大量此类功能,随着不断地发现并解决问题,我们的转化率开始持续增长。这里学到的最重要的经验是,按照页面类型以及 Web/移动 Web 对页面进行划分,借此更好地理解收益到底来自何处,并更清楚地发现不同划分中可能存在的问题。如果作为整体查看汇总后的转化率变化,这些问题可能会被遮掩起来。

有关转化率的功能清单

  • 完全相同的向上销售(Upsell)机制
  • 导航机制(弹出菜单?新标签?)
  • 注册和表单机制(字段验证信息、相同的字段和步骤)
  • 自动身份验证功能
  • 移动 Web 和平板 App 的 App 向上销售
  • 移动 Web 深度链接(Deeplinking)

性能重写过程中另一个重要的事情是对每个页面类型进行 SEO 实验。若想了解有关 SEO 实验基本功的详细信息,请查阅我们以前发布的博客文章通过实验认识 SEO 。SEO 实验可以告诉我们页面加载时间的改进是否真的能从搜索引擎带来更多流量,在我们的实验中,结论是肯定的。如果你的页面流量很大,也许可以通过实现各类功能改善搜索引擎的评级。SEO 实验还可以告诉我们某些功能的实现是否存在问题。就算一些很小的细节,例如图片尺寸或所用的 HTML 标签也会对此产生影响,因此一定要对所有页面类型进行必要的监视。我们用了几周时间找出并修复了这些问题,SEO 流量有了很大提升。

有关 SEO 的功能清单

  • 重要的标签(例如、hreflang、rel=canonical)
  • 完全相同的图片尺寸
  • 描述性文字
  • 首次页面加载的内容数量

重要经验

  • 尽可能构建完全相同的页面,不要重新设计页面
  • 针对不同类型页面分别进行实验,并区分对待 Web 和移动 Web
  • 同时别忘进行 SEO 实验
  • 针对划分的不同类型查看是否缺少某些功能,导致降低转化率或 SEO 效果

修复一个微小的转化率功能让转化率指标有了大幅提升

结果和未来计划

为了改善性能而重建页面的做法让我们用户的等待时间缩短了 40%,SEO 流量增加了 15%,注册转化率增加了 15%。由于流量和转化率之间存在倍增关系,因此对我们来说,在 Web 和应用注册方面这是一个不菲的成绩。这是我们在 2016 年赢得用户过程中获得的最大成果。此外我们网速慢的用户也能获得更好的体验。多亏了这个项目,我们的团队现在可以更自信地通过改善性能实现更大程度的用户数增长。

作者:Sam Meder, Vadim Antonov & Jeff Chang,阅读英文原文 Driving user growth with performance improvements


感谢郭蕾对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017 年 4 月 18 日 17:18778
用户头像

发布了 283 篇内容, 共 84.6 次阅读, 收获喜欢 34 次。

关注

评论

发布
暂无评论
发现更多内容

前端科普系列(1):前端简史

vivo互联网技术

html 前端 Web

安卓移动应用代码安全加固系统设计及实现

几维安全

android 安全评估 移动应用安全

工业互联网网络安全渗透测试技术研究

几维安全

网络安全 数据安全;工业互联网 移动应用安全 渗透测试

有限数据量如何最大化提升模型效果?百度工程师构建数据增强服务

百度大脑

人工智能 数据 模型训练 百度大脑

React TypeScript项目基本构建

JackWangGeek

怎么写一个超棒的 README 文档

程序员生活志

经验总结 文档

微服务框架 Dubbo

莫莫大人

极客大学架构师训练营

如何让“哑”终端进化,你知道吗?

华为云开发者社区

操作系统 物联网 IoT 华为云 LiteOS

拼多多员工曝离职黑幕:要走可以,要离职证明,没有!

程序员生活志

职场 互联网公司

Week10总结

熊威

架构师0期第十周命题作业

何伟敏

巴黎世家土味病毒营销,B端创业初期,如何用营销壮大种子用户?

北柯

创业 营销 tob

HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第7章定位

Geek_8dbdc1

libuv 异步网络编程之 TCP 源码分析

Huayra

网络编程 libuv libuv 源码分析

面经手册 · 第4篇《HashMap数据插入、查找、删除、遍历,源码分析》

小傅哥

Java 小傅哥 hashmap 面经 红黑树

智能汽车安全风险及防护技术分析

几维安全

移动应用安全

HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第11章有路网移动端主页实战

Geek_8dbdc1

合约跟单软件开发app,跟单系统开发功能和优势

WX13823153201

区块链 数字货币

肯耐珂萨D1轮融资资方阵营揭晓,跟投方为中南资本、青发集团

人称T客

看前谷歌工程师是如何副业赚钱的?

非著名程序员

程序员 个人成长 副业赚钱 提升认知

哈希算法的设计要点、应用场景

多选参数

哈希 hash 哈希算法

为什么需要企业架构师?

周金根

HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局

Geek_8dbdc1

超市趣味游戏关卡设计

孙志平

HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第9章FlexBox实战有路网

Geek_8dbdc1

Spark优化之小文件是否需要合并?

华为云开发者社区

spark 数据 cpu 内存 Spark调优

React TypeScript 项目基本构建2

JackWangGeek

React

Week10作业1

熊威

HTML5CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第10章有路网PC端主页实战整合

Geek_8dbdc1

云图说丨手把手教你为容器应用配置弹性伸缩策略

华为云开发者社区

Docker 云计算 Kubernetes 容器 云容器引擎

架构师训练营 第 10 周 作业&总结

Jam

InfoQ 极客传媒开发者生态共创计划线上发布会

InfoQ 极客传媒开发者生态共创计划线上发布会

借助性能优化促进用户数增长-InfoQ