压倒性的证据表明,网站的性能(速度)与其成功直接相关,跨越各个行业和业务指标。鉴于如此清晰的相关性(甚至已证实的因果关系),监控您的网站性能至关重要。那么,您的网站到底有多快?
首先,重要的是要理解,没有一个单独的数字可以回答这个问题。即使您已经确切定义了您想要在网站上衡量的指标,性能也会在您的用户群和您网站的不同页面之间差异很大。
我们将讨论传统上使用的主动测试技术,然后解释允许浏览器向服务器报告准确计时数据的新技术。
传统上,监控工具用于主动测试以衡量网站的性能,结果最终绘制在时间序列图上。您可以选择要测量的特定页面和要从中进行测量的地理位置,然后测试机器定期从各个位置加载页面并报告性能。结果通常非常一致,并为识别变化提供了很好的基线,但这些测量结果并不能代表实际用户。
使用主动测试来理解 Web 性能的主要限制因素是
• 页面选择。 主动测试通常只测试用户访问的页面的一小部分子集。
• 浏览器缓存。 测试机器通常在清除浏览器缓存的情况下运行,并且不显示缓存内容的影响。这包括不仅在页面之间共享的内容,还包括广泛分发的内容(例如用于社交分享小部件的 JavaScript、共享代码库以及广告系统使用的代码)。
• 机器配置。 测试机器往往是干净的配置,没有病毒、广告软件、浏览器工具栏或防病毒软件以及各种其他会干扰用户机器性能和真实世界浏览的软件。
• 浏览器。 浏览器大战从未如此激烈,各种版本的 Internet Explorer、Chrome、Firefox、Safari 和 Opera 都保持着重要的市场份额。主动测试通常仅限于少量浏览器,因此您必须尝试选择一个能够代表您的用户群的浏览器(假设您甚至有选择)。
• 连接性。 用户拥有各种各样的互联网连接,延迟和带宽差异巨大,从拨号上网到 3G 移动网络,再到有线、DSL 和光纤宽带连接。使用主动测试,您通常必须选择一些特定的配置进行测试,或者直接从数据中心执行测试。
连接性的影响不容低估。如图 1 所示,带宽会对 Web 性能产生重大影响,尤其是在较慢的速度(小于 2 Mbps)下,而延迟与 Web 性能几乎呈线性相关。
从数据中心内部进行测试会严重偏向于实际上无限的带宽和没有最后一英里延迟(对于实际用户而言,最后一英里延迟可能在 20 到 200 毫秒以上,具体取决于连接类型)。CDN(内容分发网络)加剧了连接性偏差,因为这些网络通常具有与许多监控提供商的测试机器位于同一数据中心内的边缘节点,从而将延迟降低到接近于零。
鉴于主动测试在衡量性能方面的局限性,许多工作都集中在报告最终用户在浏览网站时体验到的实际性能。从历史上看,网站已经实施了自己的解决方案来衡量和报告性能,尽管一直存在一些警告,因为页面上的 JavaScript 无法报告完整体验。从实际用户会话报告性能通常被称为 RUM(真实用户测量)。
加载页面时,浏览器通常会
• 执行 DNS 查找以将主机名映射到 IP 地址。
• 建立与服务器的 TCP 连接。
• 协商加密连接(对于 HTTPS 页面)。
• 向服务器发送页面 HTML 请求。
• 如果服务器以重定向响应,则对新位置重复上述所有步骤。
• 从服务器下载 HTML 响应。
• 解析 HTML,下载所有引用的内容,并执行页面代码。
最后一步非常复杂,并且占用了大多数网站的大部分时间(通常超过 80%4,6),并且是您可以直接从 JavaScript 测量的唯一体验部分。当使用 JavaScript 对页面进行检测以测量性能时,JavaScript 的第一次执行机会是在 HTML 从服务器下载并且浏览器开始执行代码时。这使得大约 20% 的页面加载时间超出了页面内代码的测量能力范围。多年来,人们已经实施了几种巧妙的解决方法,但从真实世界获得可靠的测量开始时间一直是使用 RUM 的最大障碍。多年来,浏览器实施了专有的指标,它们会公开这些指标,从而提供页面开始时间(主要是因为浏览器供应商也运行大型网站,并且需要更好的检测工具),但是这些实现彼此不一致,并且浏览器覆盖率也不是很好。
2010 年,浏览器供应商在 W3C 旗帜下聚集在一起,成立了 Web 性能工作组15,以标准化接口,并努力改进浏览器中 Web 性能测量和 API 的状态。(截至撰写本文时,浏览器对各种计时和性能信息的支持各不相同,如表 1 所示。)
在 2010 年末,该小组发布了 导航计时规范9,此后该规范已在 Internet Explorer(9+ 桌面和移动版)、Chrome(15+ 所有平台)、Firefox(7+)和 Android(4+)中实现。
导航计时的最大好处是它公开了许多导致 HTML 加载的计时,如图 2 所示。除了提供良好的开始时间外,它还公开了有关任何重定向、DNS 查找时间、连接到服务器的时间以及 Web 服务器响应请求所需时间的信息——对于每个用户和用户访问的每个页面。
测量点通过以下方式公开给 DOM(文档对象模型):performance对象,并且可以很容易地从 JavaScript 计算加载时间(或任意时间间隔)。
以下代码计算页面加载时间
var loadTime = performance.timing.loadEventStart - performance.timing.navigationStart;
只需确保在您要测量的点之后记录测量值(loadEventStart在实际加载事件发生之前不会设置,因此将侦听器附加到加载事件是了解其可用于测量的好方法)。
时间以常规 JavaScript 时间报告,可以与任意时间点进行比较
var now = new Date().getTime();
var elapsed = now - performance.loadEventStart;
关于用户时钟的有趣之处在于,它们并不总是向前移动,也不总是线性的,因此需要进行错误检查和数据过滤,以确保仅报告合理的值。例如,如果用户的计算机连接到时间服务器并调整时钟,则在两次测量之间可能会向前或向后跳跃,从而导致负时间。如果用户在手机上切换应用,则页面可能会在加载过程中暂停,直到用户再次打开浏览器,从而导致加载时间跨越数天。
W3C Web 性能小组认识到时钟问题,以及对超过一毫秒分辨率的粒度的需求,并且还引入了高分辨率时间规范。7 此时间测量与运行它的平台支持的精度一样高(至少一毫秒分辨率,但在大多数平台上远高于此),并且保证始终增加,并且不会因时钟更改而发生偏差。这使其在测量经过的时间间隔方面明显更好。它在 DOM 上公开给 JavaScript,如下所示performance.now()并且相对于页面导航开始时间。
网站现在可以报告所有用户的实际性能,并且监控和分析提供商也正在提供挖掘数据的方法(例如,Google Analytics 会报告导航计时以及业务指标2),因此网站可能已经获得了真实用户性能测量数据。Google Analytics 还提供了一个接口,用于报告任意性能数据,以便网站运营商可以添加他们想要测量的任何其他计时。3
与主动测试的结果不同,来自真实用户的数据是嘈杂的,平均值通常根本不起作用。性能数据变成了像公司其他业务指标一样的常规分析,管理者必须进行许多类似的分析,例如查看特定地区的用户,查看百分位数而不是平均值,以及查看结果的分布。
例如,图 3 显示了最近访问某个网站的访问者的页面加载时间分布(约 200 万个数据点)。在这种情况下,美国和欧洲的流量倾向于更快的加载时间,而亚洲和非洲的流量则倾向于更慢的加载时间,并且有大量用户的页面加载时间超过 11 秒。人口统计学问题推动了一些偏差(尤其是在不同地区的互联网连接方面),但这也是用于分发静态文件的 CDN 的结果。CDN 在东亚或非洲没有节点,因此一个实验是尝试为一部分流量使用不同的 CDN,并观察对真实用户的页面加载时间的积极影响。
在衡量网站性能时,需要考虑的一件事是何时停止计时。几乎每个测量工具或服务都会默认报告浏览器加载事件触发的时间。这主要是因为它是在各个网站之间一致且在各个浏览器之间基本一致的唯一明确定义的点。8 在完全静态页面的世界中,加载事件是浏览器完成加载 HTML 引用的所有内容(包括所有样式表、图像等)的点。
只要页面上的脚本不更改内容,所有浏览器都会一致地实现基本加载事件。HTML5 规范阐明了当脚本修改 DOM(添加图像、其他脚本等)时的行为,并且加载事件现在还包括动态添加到 DOM 的所有资源。此行为的显著例外是版本 10 之前的 Internet Explorer,它没有阻止动态插入内容的加载事件(因为它早于使行为明确的规范)。
加载事件之前的时间是一个出色的技术指标,但它可能无法传达页面对用户来说有多快或多慢。主要问题在于,它测量的是直到每个请求完成的时间,即使是那些对用户不可见的请求(当前显示页面下方的内容、不可见的跟踪像素等),并且它没有告诉您任何有关内容向用户显示速度的信息。如图 4 所示,一个在加载事件之前一直显示完全空白屏幕的页面和一个更早显示所有可见内容的页面,在测量加载事件时都可能具有相同的时间。
通过在页面本身加载后通过 JavaScript 加载所有内容,也很容易针对加载事件指标进行优化。这将使技术加载事件非常快速地触发,但用户体验将因此受到影响(并且将不再被测量)。
人们已经进行了多次尝试,以找到一种可以准确反映用户体验的通用测量方法
• 首次绘制时间。 如果正确实现,这可以告诉您用户看到空白白色屏幕以外的其他内容的第一时间点。这并不一定意味着用户看到了任何有用的东西(如前面的示例所示,它只是徽标和菜单栏),但它是重要的反馈,告诉用户页面正在加载。从现场一致地测量这一点没有一致的方法。Internet Explorer 公开了一个自定义的msFirstPaint时间,在performance.timing接口上,而 Chrome 在chrome.loadTimes().firstPaintTime;下公开了一个时间;然而,在这两种情况下,浏览器绘制的第一件事仍然可能是空白白色屏幕(尽管这比没有好,并且对趋势分析有好处)。
• 首屏时间。1 这衡量的是对页面的可见部分进行最后一次视觉更改的时间点。它是对更好地捕捉用户体验的基于实验室的测量的尝试。可以对其进行调整以使其工作得相当好,以揭示何时显示最后一点可见内容,但它无法区分页面上添加的小型社交按钮和整个页面延迟加载(在示例中,第一个页面在末尾添加了一个社交按钮,并且两个页面都将具有相同的首屏测量时间)。首屏时间仅在可以记录页面加载的视觉进度的实验室环境中可用。
• 速度指数。14 在尝试了几种时间点测量之后,我们改进了我们的可见测量框架,以捕捉页面随时间推移显示的视觉进度。这种表示用户体验的当前最佳方法以页面加载时的视觉进度为基础,并根据内容绘制到屏幕的速度计算指标。图 5 显示了图 4 中的示例,但包括了每一步的视觉进度。图 6 显示了如何绘制进度并计算随时间推移的未渲染区域,以将整体体验归结为一个数字。速度指数提高了捕捉用户体验的能力,但它只能在实验室中测量。它仍然需要您确定测量的终点,并且它不能很好地处理在加载时具有较大视觉变化的页面。
• 自定义测量。 没有什么比特定于应用程序的知识和测量更胜一筹。虽然没有通用的完美解决方案来衡量用户体验,但每个应用程序所有者都可以检测特定的性能点。
当浏览器遍历页面并构建 DOM 时,它们也会在到达内联脚本时执行这些脚本。它们在所有先前的脚本都已执行之前无法执行这些脚本。如果您想知道浏览器何时到达主文章,那么您只需在主文章的 HTML 之后添加一个微小的内联脚本,记录当前时间即可。当您报告性能指标时,您可以收集不同的自定义测量值并将它们也包括在内。
W3C Web 性能小组也考虑了这种用例,并创建了用户计时规范。13 它提供了一种使用performance.mark("label")标记时间点的简单方法,以及一种稍后查询所有自定义测量值的标准方法。这更多是为了标准化和易用性,因为您始终可以将计时存储在您自己的 JavaScript 变量中,但是通过使用标准接口,您还可以使第三方报告工具可以报告您的自定义指标。
这仍然不完美,因为无法保证浏览器实际上已将内容绘制到屏幕上,但它是它的良好代理。为了更准确地了解实际的绘制事件,动画计时接口可以通过以下方式请求在浏览器准备好绘制时进行回调:requestAnimationFrame()。12
社区一直渴望看到实施的一项规范是资源计时接口。11 它公开了有关浏览器为加载页面而必须发出的每个网络请求以及触发每个请求的内容(无论是样式表、脚本还是图像)的计时信息。
已实施一些安全规定来限制跨域提供的信息,但在所有情况下,都可以获得网络上发出的请求列表(和计数),以及每个请求的开始和结束时间。对于您有权查看细粒度计时信息的请求,您可以完全了解各个组件的计时:DNS 查找、连接时间、重定向、SSL(安全套接字层)协商时间、服务器响应时间和下载时间。
默认情况下,细粒度计时对于与当前页面来自同一域的所有资源都是可见的,但也可以通过为其他域提供的请求包含“Timing-Allow-Origin”响应标头来启用跨域可见性(最常见的情况是静态内容可以从中提供的单独域)。
您可以通过以下方式查询资源列表
performance.getEntriesByType
var resourceList = performance.getEntriesByType("resource");
for (i = 0; i < resourceList.length; i++)
...
使用此接口诊断现场问题的可能性是巨大的
• 检测间歇性表现不佳的第三方脚本或信标。
• 检测不同地区不同提供商的性能问题。
• 检测个人用户页面速度缓慢的最可能原因。
• 报告静态资源缓存的有效性。
• 以及更多...
默认缓冲区配置最多可存储 150 个请求,但有可用的接口可以
• 调整缓冲区大小(performance.setResourceTimingBufferSize).
• 清除缓冲区(performance.clearResourceTimings).
• 在缓冲区满时收到通知(onresourcetimingbufferfull).
从理论上讲,您可以报告所有用户的全部计时,并在事后诊断任何会话,但这将涉及大量数据。您更可能希望识别要测量或诊断的特定内容,并仅报告在客户端完成的分析结果(并且由于这是 Web,因此您可以在需要有关特定问题的更多信息时根据需要更改和改进此内容)。
如果您运行网站,请确保定期查看其性能。数据从未如此容易获得,而且往往非常令人惊讶。
W3C Web 性能工作组在过去两年中在定义对从真实用户获取性能信息和推动实际浏览器中的实现有用的接口方面取得了巨大进展。工作组非常活跃,并计划继续提高测量性能的能力,以及标准化常见性能问题的解决方案(最值得注意的是,一种在不占用页面的情况下触发跟踪信标的方法)。5 如果您有想法或建议,我鼓励您加入邮件列表10 并与工作组分享。
图 1 来源:http://www.belshe.com/2010/05/24/more-bandwidth-doesnt-matter-much/
图 2 来源:http://www.w3.org/TR/navigation-timing/
1. Brutlag, J., Abrams, Z., Meenan, P. 2011. 首屏时间:可视化地测量 Web 页面性能; http://cdn.oreillystatic.com/en/assets/1/event/62/Above%20the%20Fold%20Time_%20Measuring%20Web%20Page%20Performance%20Visually%20Presentation.pdf。
2. Google Analytics. 2012. 使用改进的网站速度报告衡量您的网站性能; http://analytics.blogspot.com/2012/03/measure-your-websites-performance-with.html。
3. Google Developers, 2013. 用户计时 - Web 跟踪 (ga.js); https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingTiming。
4. Hallock, A. 2012. 一些有趣的性能统计数据; http://torbit.com/blog/2012/09/19/some-interesting-performance-statistics/。
5. Mann, J. 2012. W3C Web 性能:持续的性能投资。IEBlog; http://blogs.msdn.com/b/ie/archive/2012/11/27/w3c-web-performance-continuing-performance-investments.aspx。
6. Souders, S. 2012. 性能黄金法则; http://www.stevesouders.com/blog/2012/02/10/the-performance-golden-rule/。
7. W3C. 2012. 高分辨率计时; http://www.w3.org/TR/hr-time/。
8. W3C. 2012. HTML5; http://www.w3.org/TR/2012/CR-html5-20121217/webappapis.html#handler-window-onload。
9. W3C. 2012. 导航计时; http://www.w3.org/TR/navigation-timing/。
10. W3C. 2013. [email protected] 邮件存档; http://lists.w3.org/Archives/Public/public-web-perf/。
11. W3C. 2012. 资源计时; http://www.w3.org/TR/resource-timing/。
12. W3C. 2012. 基于脚本的动画的计时控制; http://www.w3.org/TR/animation-timing/。
13. W3C. 2012. 用户计时; http://www.w3.org/TR/user-timing/。
14. WebPagetest 文档; https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index。
15. Web 性能工作组。W3C; http://www.w3.org/2010/webperf/。
喜欢它,讨厌它?请告诉我们
帕特里克·米南 在过去 12 年中以各种形式从事 Web 性能工作,目前在 Google 工作,以使 Web 更快。他创建了流行的开源 WebPagetest Web 性能测量工具,并在 http://www.webpagetest.org/ 上运行其免费实例,并且经常可以在论坛中找到他,帮助网站所有者了解和提高其网站性能。他还帮助创立了 WPO 基金会,这是一个专注于 Web 性能优化的非营利组织。
© 2013 1542-7730/13/0200 $10.00
最初发表于 Queue vol. 11, no. 2—
在 数字图书馆 中评论本文
大卫·科利尔-布朗 - 您对应用程序性能一窍不通
您无需在每次遇到性能或容量规划问题时都进行全面基准测试。一个简单的测量将提供您系统的瓶颈点:这个示例程序在每个 CPU 每秒 8 个请求后会明显变慢。这通常足以告诉您最重要的事情:您是否会失败。
彼得·沃德、保罗·万卡迪亚、卡维塔·古利亚尼 - 在 Google 重塑后端子集化
后端子集化对于降低成本很有用,甚至对于在系统限制内运行可能是必要的。十多年来,Google 使用确定性子集化作为其默认后端子集化算法,但尽管此算法平衡了每个后端任务的连接数,但确定性子集化具有较高的连接流失率。我们在 Google 的目标是设计一种具有降低的连接流失率的算法,该算法可以替代确定性子集化作为默认后端子集化算法。
努尔·穆宾 - 工作负载频率缩放定律 - 推导和验证
本文介绍了与每个 DVFS 子系统级别的工作负载利用率缩放相关的公式。建立了频率、利用率和比例因子(其本身随频率变化)之间的关系。这些公式的验证被证明是棘手的,因为工作负载固有的利用率也似乎在治理样本的粒度上以未指定的方式变化。因此,应用了一种称为直方图脊迹的新方法。在将 DVFS 视为构建块时,量化缩放影响至关重要。典型应用包括 DVFS 调控器和/或其他影响系统利用率、功耗和性能的层。
西奥·施洛斯纳格尔 - DevOps 世界中的监控
监控看起来可能非常令人难以承受。最重要的是要记住,完美永远不应该是更好的敌人。DevOps 使组织内部能够进行高度迭代的改进。如果您没有监控,请获取一些;获取任何东西。有总比没有好,如果您已经接受了 DevOps,那么您已经注册了随着时间的推移使其变得更好。