天天看点

《响应式Web设计性能优化》一2.1 性能度量基础

本节书摘来异步社区《响应式web设计性能优化》一书中的第2章,第2.1节,作者: 【美】tom barker 译者: 余绍亮 , 丁一 , 叶磊 责编: 赵轩,更多章节内容可以访问云栖社区“异步社区”公众号查看。

如果你正在阅读本书,很可能你已经熟知性能的含义,或是至少曾经围绕你的web应用做过一些性能相关的讨论。但在继续往下看之前,我们来确认下在术语方面我们的理解是一致的。

如若这是你首次听到web性能优化一词,赶快去搞一本steve souders的high performance web sites和even faster web sites(均由o’reilly出版)读一读。这些都是web性能的标准,也是所有web开发者都应掌握的基础知识。

本章并不打算覆盖性能的每个细节。从前面提到的steve souders的著作开始,已经有大量的资料在讲这些东西。但是,本章的目标是对性能(web性能和web运行时性能)做个概述,包括一些性能度量的工具。这样一来,后面章节我们说到这些概念时,就不会再有歧义和混淆了。

当提及网站和web应用性能的时候,我们说的要么是web性能,要么是运行时性能。我们将web性能定义为,一个终端用户从请求一段内容开始到这段内容显示在用户设备上这段时间的度量值。我们将运行时性能定义为,应用在运行时对用户输入响应能力的一个标示。

应当意识到,针对你的web应用性能进行量化和标准的制定,是应用的一个关键方面。web性能和运行时性能都有一些指标可以进行实证测度和量化。本章中,我们来看一看这些指标,以及可以用来量化这些指标的工具。

注意 性能指标是组织机构用来定义一次尝试是成功或是失败的可量化目标。通常称作关键性能指标,缩写为kpi。

本章我们将谈到的性能指标类型如下所示。

定量指标

可以通过实验进行度量的一种目标(如某个东西的数量)。

定性指标

不能通过实验度量的一种目标(如某个东西的质量)。

先行指标

用于预测结果。

输入指标

用于度量某个过程中消耗的资源。

什么是web性能?

想想每次浏览网页的过程。打开浏览器,键入url,然后等待网页加载。从键入url后按下回车键(或是从书签列表中点击某个书签,亦或是点击页面中的某个链接),到页面渲染,这之间消耗的时间就是所浏览页面的web性能。若站点运行正常,这个时间甚至不应该被人感受到。

web性能的定量指标数不胜数。

页面加载时间。

页面文件大小。

http请求数。

页面渲染时间。

web性能的定性指标总结起来比较简单:速度感。

在看这些指标之前,先来讨论下页面是如何到达浏览器并展现给用户的。当通过浏览器请求一个web页面,浏览器会创建一个线程去处理这个请求,随后开始远程dns查找,远程dns服务器会将你输入的url对应的ip地址返回给浏览器。

接着,浏览器通过与远程web服务端的三次握手来建立一个tcp/ip连接。这个握手由浏览器与远程服务端之间的syn、syn-ack以及ack消息组成。

200表示服务端成功响应。

301表示永久重定向。

302表示临时重定向。

403表示请求被拒绝。

404表示服务端找不到请求的资源。

500表示处理请求时出错。

503表示服务不可用。

504表示网关超时。

图2-1是tcp事务的时序图。

《响应式Web设计性能优化》一2.1 性能度量基础

图2-1 浏览器和web服务器的协商过程

要时刻记得,加载一个html页面不只需要一次这个过程,浏览器还要为页面链接的每个资源发起一个http请求——所有的图片、链接的css和javascript文件以及其他类型的外部资源(但是要注意,只要后续的http请求连接的是相同的源,浏览器就可以重用相应的tcp连接)。

当浏览器收到页面的html后,就开始解析并渲染页面内容。

浏览器用其渲染引擎来解析和渲染内容。现代的浏览器架构由几个关联的模块组成。

ui层

这一层为浏览器绘制界面。有些元素,如地址栏、刷新按钮以及用户界面上(ui)的其他元素是浏览器自身的。

网络层

该层处理网络连接,承担的职责有建立tcp连接以及处理http的往返过程。网络层处理内容下载,然后将内容传递给渲染引擎。

b

渲染引擎负责将内容绘制到显示器上。浏览器制造商会将他们的渲染引擎以及javascript引擎打上商标并对外授权。所以,相对流行的渲染引擎你可能已经听说过了。可以说,最流行的渲染引擎是webkit,chrome(blink是它的译名)、safari、opera以及其他一些浏览器中都用到了webkit。当渲染引擎遇到了javascript,会将其传递给javascript解释器。

javascript引擎

javascript引擎会解析并执行javascript。如同渲染引擎,浏览器制造商给他们的javascript打上商标进行授权,很可能你已经听说过它们了。一个流行的javascript引擎是google的v8,chrome、chromium中都用到了它,node.js就是用它作为引擎的。

图2-2展示了这样的架构。

《响应式Web设计性能优化》一2.1 性能度量基础

图2-2 分成多个模块组件的现代浏览器架构

设想这样一个用例,用户在浏览器地址栏里键入一个url。ui层将这个请求传递到网络层,网络层随后建立连接,然后下载初始页面。当含有html块的数据包到达,就被传递给渲染引擎。渲染引擎将html组装成原始文本,然后对文本中的字符开始进行词法分析——或解析。这些字符会与一个规则集相比较——我们在html文档中指定的文档类型定义(dtd)——然后转换成基于规则集的符号。dtd规定了一系列标签,这些标签组成了我们将要使用的语言版本。这些标签就是由一些被分隔成有意义片段的字符组成。

这里有个网络层是如何处理并返回下列字符串的例子。

这串字符会被分割成下面这样有意义的块。

渲染引擎拿到这些符号后将它们转换成文档对象模型(dom)元素(dom是页面元素的内存表现形式,也是javascript用于访问页面元素的api)。dom元素被布局成一棵渲染树,渲染引擎会迭代该树。首次迭代中,渲染引擎会布局好dom元素的位置;下一次迭代就将这些元素绘制到屏幕上。

如果渲染层在解析和符号化过程中发现了script标签,就会暂停下来然后评估下接下来要进行的处理。如果script标签指向一个外部javascript文件,解析过程暂停,随后网络层介入,下载javascript文件,然后初始化javascript引擎解析,执行该文件。如果script标签包含的是内嵌的javascript,渲染引擎暂停,javascript引擎被初始化,内嵌的javascript会被解析与执行。执行完成后,之前暂停的渲染过程会恢复运行。

这是一个很重要的细微差别,影响的不仅仅是dom元素何时对javascript可见(我们的代码可能会尝试访问页面上的一个元素,但该元素可能还没有被解析和符号化,更不用提渲染了)和性能。例如,我们是想要阻塞页面的解析直到下载并运行了那一段代码吗,或是如果我们先展示内容再去加载页面的代码,页面的功能能否正常?

图2-3描绘了这种工作流程。

《响应式Web设计性能优化》一2.1 性能度量基础

图2-3 浏览器中内容加载和渲染的工作流程

了解网页内容是怎样传递给浏览器对于理解web性能影响因素是至关重要的。也要注意到,由于浏览器的快速更新,浏览器厂商可能会时常对这个工作流进行调整和优化。

既然我们已经了解了内容传递和展现的架构,那来看一看在这个传递工作流上下文中的性能指标。

http请求数

时刻记住,当浏览器获取html页面时会创建一个http请求,还会创建更多的http请求来获取页面中链接的每个资源。根据网络延迟情况,每个http请求都会使总的页面加载时间增加20~200毫秒(如果考虑可以并行加载资源的浏览器,这个数字会有所不同)。如果只是少量的资源,这些额外的加载时间可以忽略不计,但如果是100个或更多的http请求,将会显著加大总体web性能的延迟。

减少页面需要的http请求数才有意义。开发者有很多办法可以做到,如将不同的css或javascript文件合并成单个文件,将常用的图片合并成单个的称之为sprite的图片文件。

页面负载

影响web性能的因素之一是页面的总文件大小。总负载包括组成该页面的html、css以及javascript累计的文件大小。还包括所有的图片、cookie以及其他嵌在页面中的媒体。

页面加载时间

http请求数以及总的页面负载本身只是输入,但web性能方面需要关注的真正kpi是页面加载时间。

页面加载时间是最明显的性能指标,也是最容易量化的。简而言之,它是浏览器下载并渲染所有页面内容的时间。以前,度量的是从页面请求到页面(窗口加载,window onload)事件之间消耗的时间。最近,由于开发者越来越喜欢在页面完成加载之前就提供好的用户体验,这样度量结束的时间点就会移动,甚至完全改变。

特别是,在有一些用例中,window.onload事件触发之后,可以动态加载内容——比如,如果内容是延迟加载的,就会出现这种情况——并且有一些用例,在window.onload事件触发之前页面就是可用的,看起来也是完整的(如先加载内容,然后再加载广告)。这些用例会降低依靠window.onload事件追踪特定页面加载时间的有效性。

有一些选择可以规避这个难题。webpagetest的创建和维护者pat meenan,在webpagetest中加入了一种度量方式,称为速度指标(speed index),其实质上是对页面内容渲染快慢计分。有一些开发团队创建了自己自定义的事件,来追踪他们觉得用户体验关键页面的各个部分是何时加载的。

无论你选择何种方式进行追踪,页面的加载(即,你的内容已经准备好接受用户交互)都是应当监控的关键性能指标。

继续阅读