页面加载与API服务响应--- 性能标定与标准

前言

本文涉及性能场景分析、问题分析与标准逻辑推导。

提出了以用户为中心的目标性能标定及时间参考标准。

标准会持续更新,希望可以通过更多更合理场景分析,解决问题。


页面加载与交互响应是影响用户使用的关键因素。过于长的等待时间或操作响应延迟都会影响用户的正常使用。为了保证软件的正常使用,需要制定一个可行的优化标准与最低标准。解决关键问题,不断提升性能,以达到解决困扰用户使用问题的目的。


资源加载

终端加载资源包括静态资源动态资源两种。


静态资源是包括面页显示资源、业务交互逻辑脚本资源、图片、声音、文字等没有状态的资源。一般是只加载一次,或不存在业务上变化逻辑的资源。


动态资源指的是所有数据资源,都是有状态需要持久化的资源。一般是通过特定的后端服务提供的并且存在业务变化逻辑的资源。如:用户列表、用户信息、商品信息、图表数据信息等。


数据加载

用户执行一个操作,并在页面上显示数据的交互过程几乎占据了所有应用交互场景的80%。尽管这是一个非常普通的交互过程,但API响应的延迟会直接影响功能能否正常使用。从页面执行用户具体操作行为开始,直到数据呈现在页面上,整个过程包含了6个步骤:

1. 发出请求。

2. 服务器接收到请求。

3. 服务器整理数据。

4. 服务器返回数据。

5. 页面接收返回的数据。

6. 页面渲染并呈现返回的数据。

其中2、5会受到具体网络情况影响。(如:网络延迟、网络带宽等)。剩下影响响应时间的与设计开发相关的项就只有:

1. 发出请求。

2. 服务器整理数据。

3. 服务器返回数据。

4. 页面渲染并呈现返回的数据。

通常情况下,除了对用户提交的数据做预处理操作可能会耗时外,“1. 发出请求”这个过程不会消耗时间,几乎立即就执行了,即使是消耗时间,也是离线的与网络无关的,也就是算法与具体逻辑实现上的耗时,并且是可以通过优化逻辑与算法解决(此处不展开讨论算法性能)。

“2. 服务器整理数据”这个过程可能是API响应流程中最耗时的一步。一般问题都出在数据查询(如:数据库操作效率低,逻辑冗余等),或从者从其它服务获取数据。(如图)

数据经过的逻辑节点
发现性能瓶颈

通常“3. 服务器返回数据”时会按照特定的要求或数据格式返回,如:JSON/XML/AMF/RO等,与服务器端原生的数据格式完全不同,这就需要把整理好的原生数据转换成目标数据格式。在数据转换的过程中,如果对转换算法处理不恰当或算法效率低,就要造成大量的性能消耗。另外,在数据对象转换的时,会存在对象转换装箱拆箱这种效率很低、性能消耗大的场景。

不处理数据

API响应

有很多潜在因素都可能会延缓服务器响应,例如应用逻辑缓慢、数据库查询缓慢、路由缓慢、框架、库、资源CPU不足或内存不足等。需要考虑所有这些因素,才能改善服务器的响应时间。要找到服务器响应时间过长的原因,首先要进行测量。然后,准备好相关数据,并参阅有关如何解决该问题的相应指导。问题解决后,还必须继续测量服务器响应时间,并解决将来出现的性能瓶颈问题。


通过上面已经提的,可以得到组成交互响应的时间是由:请求接收时间 + 数据整理时间 + 格式转换时间 + 数据返回接收时间组成。简化下来就是:

响应时间 = 等待返回 + 加载内容

当网络传输带宽既定时,单纯加载内容的时间就基本固定了,也就是说通过网络传输传固定长度的内容所用的时间是固定的(或可预测的)。从上面的公式来看,减少“响应时间”的关键就在“等待返回”这个关键要素上了。

(下图为通过chrome-dev-tool network工具对一个普通XMLHttpRequest时间消耗的分析)

(TTFB: Time To First Byte)浏览器等待首个数据返回的时间

Waiting (TTFB) 是服“等待返回”的时间,其中包括:整理数据、转换格式的时间。图上所示:

Request过程基本不耗时间,可以忽略。

Waiting响应的等待时间占了总消耗时间的90%,而实际的数据下载只用了不到10%的时间。除了下载大文件以外,几乎所有业务的返回数据都很小,从网络带宽传输的角度看,传输这些数据根本都不是问题,并且都能做到毫秒级别。所以,减少等待的时间是直接提升API请求响应性能的关键。

时间标定

从一个完整的页面交互过程看,造成页面性能消耗的时间分布总体上如下图所示:

可以总结出时间消耗为:

总时间 = UI渲染 + 建立连接(网络延迟) + 数据服务


从“用户感知时间长度”的实验得出的结论可以为用户感知交互做以下分级:

【用户感知】      【响应时间】
  :流畅          :< 1.0s
  :可用          :1.0s ~ 2.0s
  :丢帧          :[纯页面性能指标]
  :卡顿          :3.0s ~ 5.0s
  :阻塞          :> 5.0s


假设:要在1s内完成页面渲染展示。如下图所展示,实际有600ms的强制网络开销并且你无法做任何事,而只有400ms的时间去做服务器优化与客户端的性能优化。

渲染页面时间分布

再以“用户感知级别:可用”为参考的目标性能指标,可以得到“总时间”为1.0s ~ 2.0s。这里取一个平均值1.5s(即1500ms),再减去网络延迟开销(n),剩下的就是可以实际参考的【性能优化的目标时间】了。

这里,通过Google官方分析大量用户与网站数据实际得出的结论是:页面布局渲染的理想时间为200ms。如图:

google page-speed tool

所以需要为上面公式中“UI渲染”这一项分配200ms。

通常情况下网络延迟没有确定的时间,而且移动网络与非移动网络的延迟差距也不小。做为性能要求很高的游戏服务器的网络延迟开销一般控制在200ms~400ms以内。这里给网络开销取一个相对严苛的时间数值:400ms。

通过以上这些数据不难推出一个公式:

总时间 - UI性能 - 网络延迟 = 数据服务

把各部分调研出的目标时间带入公式最后得到:

(总时间)1500ms - (UI性能)200ms - (网络延迟)400ms = (数据服务)900ms

[数据服务]时间 = 900ms

也就是说,数据服务最大响应的时间在900ms以内,才是可以满足基本可用的实际用户交互服务目标。

以上计算过程只是一个定量推导计算过程,不是定性的实际场景结果。但通过公式不难看出,页面加载与API响应指标可优化提升的时间空间基本上满足公式给出的结论。再对比上面给出的“用户感知”时间分级,考虑实际要为用户提供服务的目标要求,也可以为数据服务给出时间分级。


API响应时间分级:

 :< 100ms                  流畅
  :100ms ~ 200ms           可用
  :500ms ~ 1000ms          卡顿
  :2000ms ~ 5000ms         阻塞
  :> 5000ms               [超时或不可用]


然而,由于网络连接性能有很大差异,因此,只考虑网页性能中与网络无关的方面:服务器配置、网页的HTML结构及其所用的外部资源(例如,图片、JavaScript和CSS)。实施这些建议应该能改进网页的相对性能。但网页的绝对性能将仍取决于用户的网络连接。


页面加载

从用户输入地址或点击操作触发浏览器发出加载请求开始。请求通过网络到达服务器,服务返回页面描述信息(html文件)给浏览器。然后,浏览器解析html页面文件,得到了需要加载逻辑脚本(js文件),样式描述文件(css文件),图片文件等内容后,继续向服务器请求这些内容资源,服务器返回指定的目标资源。(如图)

从上图来看如何减少请求数量,也是降低页面整体加载时间消耗的一种方法。

减少请求数。


以下是针对页面加载性能给出的建议


避免目标网页重定向

重定向会触发额外的HTTP请求响应周期,并会额外延长往返时间延迟,因此,将应用发出的重定向数量降至最低至关重要。避免HTTP重定向可以缩减用户等待页面加载的时间。这里建议仔细斟酌设计,看看可以在哪些方面提升网站性能。


启用压缩功能

网络服务器可以通过调用第三方模块或使用内置程序将文件压缩为gzip格式,然后再发送该压缩文件以供下载。这样可以在下载呈现网站所需的资源时,节省一些时间。

启用压缩功能。参考某些热门网络服务器上所启用的压缩功能:

  • Apache:采用mod_deflate
  • Nginx:采用HttpGzipModule
  • IIS:配置HTTP压缩功能


改善服务器响应时间

服务器响应时间表示加载必要HTML以开始呈现服务器所托管网页的时间,其中减去了服务器之间的网络延迟时间。每次运行所用的时间可能会有所不同,但这种差异不应太大。事实上,如果服务器响应时间变化很大的话,则表明性能上可能存在问题。

应将服务器响应时间控制在200毫秒以内。有很多潜在因素都可能会延缓服务器响应,例如应用逻辑缓慢、数据库查询缓慢、路由缓慢、框架、库、资源CPU不足或内存不足等。需要考虑所有这些因素,才能改善服务器的响应时间。要找到服务器响应时间过长的原因,首先要进行测量。然后,准备好相关数据,并参阅有关如何解决该问题的相应指导。问题解决后,还必须继续测量服务器响应时间,并解决将来出现的性能瓶颈问题。

  1. 收集并检查现有性能和数据。如果没有可用内容,请使用自动网页应用监测解决方案(可在市面找到一些托管的开源版本,它们适用于大多数平台)进行评估,或添加自定义的方法。
  2. 识别并修复首要的性能瓶颈问题。如果使用的是热门Web框架或内容管理平台,请参阅有关性能优化最佳做法的文档。
  3. 监测并提醒任何将来出现的性能衰退问题!


使用浏览器缓存

用户会多次访问应用服务,缓存静态资源在浏览器端可以节省内容加载的时间。缓存标头应当添加到所有可缓存的静态资源中,而不仅仅是应用到一小部分静态资源(例如,图片)中。可缓存的资源包括JS和CSS文件、图像文件及其他二进制对象文件(媒体文件和PDF文件等)。通常情况下,HTML不是静态资源,默认情况下不应被视为可缓存资源。应考根据实际情况虑哪些缓存策略适用项目的HTML。


缩减资源大小

缩减资源大小是指删除不必要的字节(例如,多余的空格、换行符和缩进)。压缩HTML、CSS和JavaScript可提高下载、解析和执行的速度。除此以外,对于CSS和JavaScript,还可通过第三方工具或工程化工具进一步缩小文件体积:在对HTML进行适当更新的过程中重命名变量名称,以确保选择器继续运行。


优化图片

尽量减小图片尺寸,以减少用户等待资源加载的时间。适当地设置图片的格式并进行压缩可以节省大量的数据字节空间。这样可以为那些网络较差、连接较慢的用户节约时间,还可以为有流量套餐限制的用户节省成本。

应对所有图片进行基本优化和高级优化。基本优化包括裁剪不必要的区域,将颜色深度降至可接受的最低水平,移除图片评论以及将图片保存为恰当的格式。还可以使用任意图片编辑程序(例如,GIMP)执行基本优化。高级优化包括对JPEG和PNG文件执行进一步的压缩(无损压缩)。


1. 使用图片压缩工具

市面上有许多工具可用来对JPEG和PNG文件执行进一步的无损压缩,并且不会对图片质量造成任何影响。对于JPEG文件,这里建议使用jpegtran或jpegoptim(仅适用于Linux;使用--strip-all选项运行)。对于PNG文件,建议使用OptiPNG或PNGOUT。

2. 选择恰当的图片文件格式

尽管我在下面推荐了一些较高级别的格式,但还是建议测试一下哪种格式最适合项目的实际情况:

  • PNG格式几乎一直优于GIF格式,尽管某些旧版浏览器只能为PNG格式提供部分支持。
  • 为较小或简单的图形(例如,小于10x10像素的图形或调色板小于3色的图形)以及包含动画的图片使用GIF格式。
  • 为所有摄影风格的图片使用JPG格式。
  • 请勿使用BMP格式或TIFF格式。


优化CSS发送过程

屏幕显示内容之前,浏览器会阻止外部CSS文件。这会导致额外的网络延迟,并延长屏幕显示内容的时间。

如果外部CSS资源较小,就可以直接将这些内容插入到HTML文档中,这就是通常说的“内嵌”。通过这种方式内嵌较小CSS资源,浏览器可以继续呈现网页。请注意,如果CSS文件较大,完全内嵌CSS可能会导致页面首屏加载内容部分的体积过大。如果CSS文件较大,就需要权衡内嵌呈现首屏内容所需的CSS,并且暂缓加载其余样式,直到首屏内容显示之后为止。

内嵌较小CSS文件的示例:

HTML文件内容
外部CSS文件内容

内嵌关键的CSS,具体方法如下:

在网页加载之后,原始small.css才会加载。通过JavaScript将所有<style>和<link>元素插入到文档中,以维护CSS规则的应用顺序。

请勿内嵌较大数据URI
在CSS文件中内嵌数据URI时,请务必慎重。可以在CSS中选择使用较小数据URI,因为内嵌较大数据URI会导致首屏CSS变大,进而延缓网页呈现时间
请勿内嵌CSS属性
应尽量避免在HTML元素(例如,< p style=...>)中内嵌CSS属性,因为这经常会导致出现多余的重复代码。此外,内容安全政策(CSP)会在默认情况下阻止在HTML元素上内嵌CSS。


按优先级排列可见内容

如果所需的数据量超出初始(Slow Start)拥塞窗口(Congestion Window)的限制,系统就需要在服务器和用户浏览器之间进行更多次的往返。如果用户使用的是延迟时间较长的网络(例如,移动网络),该问题会严重延迟网页的加载。

为提高网页加载速度,需要限制呈现网页首屏内容所需的数据大小(如:HTML标记、图片、CSS和JavaScript)。可以尝试以下几种方法:


1. 结构化HTML,以便首先加载关键的首屏内容

首先加载网页的主要内容。结构化网页,以便服务器发出的初始响应能发送必要数据,从而迅速呈现网页的关键部分并暂缓呈现其余部分。这可能意味着,我们必须将CSS拆分为两个部分:负责调整内容ATF部分的格式的内嵌部分,以及可暂缓呈现的部分。

(“ATF”一词源自传统出版业,指的是报纸头版的中折线以上区域,这块黄金区域往往用来刊登最有吸引力的新闻。延伸到互联网领域,ATF 指的是页面中不需要滚动就可以看到的首屏内容。)
  • 如果HTML先加载第三方小部件,再加载主要内容,请将该加载顺序更改为先加载主要内容。
  • 如果页面采用的是两列布局(即导航边栏加文章),而HTML先加载边栏,再加载文章,可以考虑首先加载文章。

2. 减少资源所用的数据量

如果经过重新设计的应用页面可以在多个设备上正常运行,并且也能首先加载关键内容,还可以使用以下技术来减少呈现网页所需的数据量:

  • 缩减资源的大小:通过移除不必要的空格和评论来缩减HTML、CSS和JavaScript的大小。通过使用可重命名资源中变量名称的工具,实现进一步的优化。
  • 尽可能考虑使用CSS,而非图片。
  • 启用压缩功能


移除阻止呈现的JavaScript

浏览器必须先解析网页,然后才能将其呈现给用户。如果浏览器在解析过程中遇到外部脚本,就会终止解析过程而去下载这个外部脚本。每当遇到这种情况时,浏览器都会增加一个网络往返(round-trip)过程,这样就会导致首次呈现页面的时间变长,延迟加载。

建议以内嵌方式处理首屏加载区域所需的Javascript脚本,并且让为页面延迟加载其他功能所需的Javascript脚本,直到首屏内容发送完毕为止。注意,要通过这种方式缩短加载时间,我们还必须优化CSS发送过程

1. 内嵌较小的JavaScript

如果外部脚本较小,可以直接将它们添加到HTML文档。通过这种方式内嵌较小文件可让浏览器继续呈现网页。例如:

html文件
资源small.js
内嵌脚本

这样将small.js内嵌在HTML文档中,就可以消除对它的外部请求。


延迟加载JavaScript

为防止JavaScript阻止网页加载,可以使用以下方法:

  1. HTML异步属性。如:`<script async src="main.js">`
  2. 将Javascript脚本放到所有HTML内容最后与结束</body>之前。
  3. 通过第三方加载库工具在合适的时间点动态加载Javascript脚本。

需要注意的是:异步加载JavaScript时,如果页面加载互相依赖的脚本,请务必谨慎,以确保应用以合适的依赖顺序加载脚本。


一些可操作建议:

适当的过度

在有页面跳转的场景中,加入过度效果或过场动画,可以有效的缓解用户感知层面的延迟,能避免由于延迟造成的页面假死的假象,也可以为页面争取一些时间,可以做更多的事情。

在有表单提交操作的页面,或有数据处理时间要求的页面,加入处理进度,可以给用户带来更友好的交互体验。

对于有实时性数据要求的页面,使用更高效的网络通信技术,如:socket、long-polling等。


页面性能分析

性能分析,往往需要查看 CPU 耗时,了解瓶颈在哪里。页面性能分析可以使用很多浏览器自带的工具,如:chrome的开发者工具。下面介绍一种“火焰图”(flame graph)是性能分析的利器。以及它的基本用法。

火焰图的含义

火焰图是基于性能数据分析结果产生的 SVG 图片,用来展示 CPU 的调用栈。

y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。

x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。

火焰图就是看顶层的哪个函数占据的宽度最大。只要有"平顶"(plateaus),就表示该函数可能存在性能问题。

颜色没有特殊含义,因为火焰图表示的是 CPU 的繁忙程度,所以一般选择暖色调

这里有一张chrome浏览器 开发者工具 性能分析 的结果图(图是颠倒的火焰,但原理是一样的)

通过工具给页面渲染过程性能进行分析。找出性能问题。

下图中的示例是工具自动标红了一个事件处理句柄function。提示函数可能点用CPU时间过长。


关于火焰图与性能分析更多的资料请参与相关文档。这里不过多赘述。推荐资料:


[如何读懂火焰图? - 阮一峰的网络日志](如何读懂火焰图? - 阮一峰的网络日志)


[如何使用 Timeline 工具 | Tools for Web Developers | Google Developers](developers.google.com/w)


[Performance Analysis Reference | Tools for Web Developers | Google Developers](developers.google.com/w)


网络

使用CDN

用户与Web服务器的距离直接响应响应时间。 在多个分布在不同地理位置的服务器上部署应用的内容,将使的从用页面户的角度更快加载。

作为实现地理上分散的内容的第一步,不要尝试重新设计应用以适应分布式架构。 根据应用的不同更改架构可能使任务变的更艰巨,如:同步会话状态和跨服务器位置复制数据库事务。 尝试缩短用户与内容之间的距离可能会延迟或不能通过此应用程序体系结构步骤。

记住,80-90%的最终用户响应时间用于下载页面中的所有组件:图像,样式表,脚本,Flash等。这是性能黄金法则。 而不是从重新设计应用程序体系结构的艰巨任务开始,最好先分散Web应用的静态内容。 这不仅可以大幅缩短响应时间,而且由于CDN服务这更容易实现。

内容传送网络(CDN)是分布在多个位置的网络服务器的集合,以更有效地向用户传送内容。 选择用于将内容递送给特定用户的服务器通常基于网络邻近度的度量。 例如,选择网络跳数最少的服务器或响应时间最快的服务器。

一些大型互联网公司拥有自己的CDN,但使用CDN服务提供商是具有成本效益的。 对于创业公司和私人网站来说,CDN服务的成本可能会很高,但是随着目标受众越来越大并且变得更加全球化,CDN是实现快速响应所必需的。 在雅虎,将静态内容从其应用程序Web服务器移到CDN(如上所述的第三方以及雅虎自己的CDN)的属性将最终用户的响应时间提高了20%甚至更多。 切换到CDN是一个相对简单的代码更改,将显着提高应用的速度。


减少DNS查找

域名系统(DNS)将主机名映射到IP地址,就像电话本将人名映射到他们的电话号码一样。 当在浏览器中键入yahoo.com时,浏览器联系的DNS解析器会返回该服务器的IP地址。 DNS有成本。 DNS通常需要20-120毫秒才能查找给定主机名的IP地址。 直到DNS查找完成,浏览器才能从此主机名下载任何内容。

DNS查找缓存能提供更好的性能。 这种缓存可以在由用户的ISP或局域网维护的特殊缓存服务器上,在个人用户的计算机上也可以缓存。 DNS信息保留在操作系统的DNS缓存中(Microsoft Windows上的“DNS客户端服务”)。 大多数浏览器都有自己的缓存,与操作系统的缓存分开。 只要浏览器在自己的缓存中保存了一条DNS记录,就不会访问操作系统的缓存了。

按照DnsCacheTimeout注册表设置的指定,Internet Explorer默认缓存DNS查找30分钟。 Firefox缓存DNS查找1分钟,由network.dnsCacheExpiration配置设置控制。 (Fasterfox将其更改为1小时。)

当客户端的DNS缓存为空(浏览器和操作系统都为空)时,DNS查找的数量等于网页中唯一主机名的数量。 这包括页面URL,图像,脚本文件,样式表,Flash对象等中使用的主机名。减少唯一主机名的数量可以减少DNS查找的次数。

减少唯一主机名的数量有可能减少页面中发生的并行下载量。 避免DNS查找会缩短响应时间,但减少并行下载则可能会增加响应时间。 这里的准则是将这些组件分成至少两个但不超过四个主机名。 这在减少DNS查询和允许高度并行下载之间取得了很好的权衡。


没有404

HTTP请求是昂贵的,所以发出一个HTTP请求并得到没有实际用处的响应结果(即,404 Not Found)是完全没有必要的,并且会减少用户体验而没有任何好处。 有些网站有404帮助页面(“你的意思是XXX?”),这对用户体验很好,但也浪费了服务器资源(如数据库等)。 更糟的是,当连接到外部JavaScript的错误,结果是404。首先,这个下载行为将阻止并行下载。 接下来,浏览器可能会尝试解析404响应正文,就好像它是JavaScript代码一样,试图找到可用的东西。


减小Cookie大小

HTTP cookie用于各种情况(如身份验证和个性化)。 cookie信息会在Web服务器和浏览器之间的HTTP标头中交换传递。 尽可能降低cookies的大小,以尽量减少对用户响应时间的影响。

  • 消除不必要的cookie。
  • 尽可能降低Cookie大小,以尽量减少对用户响应时间的影响。
  • 在相应的域级别设置Cookie,以便其他子域不受影响。
  • 适当地设置过期日期。 较早的过期日期或不更早删除cookie,提高用户响应时间。


为静态资源使用无Cookie域

当浏览器发出一个静态图像的请求,会将cookie与请求一起发送,对于服务器来说这些cookie没有任何用处。 所以这个行为只是增加网络流量而已。 应该确保请求静态组件时是无cookie的请求。 可以创建一个子域,并在那里管理所有的静态组件。

例如,应用的域名是www.example.org,我们可以在static.example.org上托管应用的静态组件。 但是,如果已经在顶级域example.org上设置了cookie,而不是www.example.org,那么对static.example.org的所有请求都将包含这些cookie。 在这种情况下,就可以使用一个全新的域名,在那里托管静态组件,并保持此域名无cookie。(如:雅虎 使用yimg.comYouTube使用ytimg.com,亚马逊使用images-amazon.com等)。

在无Cookie域上托管静态组件的另一个好处是,某些代理可能会拒绝缓存使用cookie请求的组件。 在相关说明中,如果想知道是否应将http://example.org或http://www.example.org用于目标项目的主页,请考虑cookie的影响。 省略www让你别无选择,只能将cookies写入* .http://example.org,所以出于性能原因,最好使用www子域名并将cookies写入该子域名。


减少多往返数据传递

出于对TCP连接能力的评估(即TCP慢启动),新的TCP连接不能立即使用客户端和服务器之间的全部可用带宽。 因此,服务器在第一次往返传输时可以在一个新的连接上发送多达10个TCP数据包(大约14KB的数据),然后必须等待客户端确认这些数据,然后才能扩展拥塞窗口(Congestion Window)并继续传送更多数据。

由于TCP的这种行为特性,着重优化数据内容大小 ,以尽量减少传递数据的往返次数来加快页面或数据的呈现。 理想情况下,ATF的内容应该在14KB以下 - 这样浏览器只需一次往返就可以绘制页面。 此外,十分重要的是要注意,10数据包(IW10)限制是TCP标准的最新更新:应确保将服务器升级到最新版本以利用此更改。 否则,限制将可能是3-4包!


欢迎提供更多的建议丰富我们的内容。

未完待续 ... ...


文档中所设计到的数据及部分参考资料:


[Best Practices for Speeding Up Your Web Site - Yahoo Developer Network](Best Practices for Speeding Up Your Web Site)


[Response Time Limits: Article by Jakob Nielsen](Response Time Limits: Article by Jakob Nielsen)


[Mobile API response time matters: 4 steps to speed up | TechBeacon](techbeacon.com/mobile-a)


Why use a Content Delivery Network (CDN)?


作者 *zonebond* *zonebond@126.com*


更多技术文章,请关注:[知乎专栏](zonebond)

编辑于 2018-02-26

文章被以下专栏收录