HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

使用 HMTL5 API 监控前端性能

  • 2015-10-13
  • 本文字数:3363 字

    阅读完需:约 11 分钟

用户计时 API

用户计时 API 可以在网页应用中测量两个预定义标记之间的性能。开发者仅仅需要分别定义测量的开始和结束标记。可以通过 JavaScript 对象“ performance ”提供的函数,对计时位置进行标记。

var measuring_start = performance.now();通过“ now ”函数,可以在网页应用的获取计时用高精度时间戳。和该函数类似的是Date 对象,它同样可以获取当前时间戳。二者的主要区别是时间精度,now 函数的返回值的w3c 文档中明确要求,必须能够表示精确到千分位小数的毫秒值。另外now 函数返回的数值,是从浏览器的“浏览开始事件(navigationStart)”开始到现在的毫秒数。

复制代码
performance.now()
35438640.775000006
(new Date()).getTime()
1443063066478

如果希望分析一个图片的加载性能,可以在图片的加载(load)事件中设置第二个标记。图片加载的耗时,就是“measure_start”和“measure_end”两个变量之间的差值(单位毫秒)。

复制代码
<html>
<head>
<meta charset="utf-8" />
<title>test timing</title>
</head>
<body>
<img src="http://cdn3.infoqstatic.com/statics_s2_20150922
-0305u1/styles/i/logo_bigger.jpg" alt="image" >
<script type="text/javascript">
var measure_start = performance.now();
document.getElementsByTagName("img")[0].addEventListener
("load", function() {
var measure_end = performance.now();
console.log("image load time: " + (measure_end - measure_start) + "ms");
}, false);
</script>
</body>
</html>

访问这个 html 之后,可以在控制台看见输出:

image load time: 24.395ms同时,可以和 Chrome 开发者工具中网络标签页的加载时间做比较:

(点击放大图像)

除了使用now 函数直接获取时间戳之外,Performance 接口还提供了标记(mark)函数。开发者可以在任何需要记录时间的地方创建、清除标记。

复制代码
performance.mark("start");
performance.mark("end");

mark 函数不返回任何值,但是后续可以通过标记的名称来获取标记的数据。如果要计算标记之间的差值,可以通过“measure”函数来完成。该函数需要三个参数,第一个参数定义了该差值的名称,第二个和第三个变量指定标记的名称。同样,该函数也不返回任何值。

performance.measure("difference", "start", "end");上面这个例子,计算了“start”和“end”两个标记之间的差值,并将差值命名为“difference”。需要特别注意的是,这里相同的名称都会被记录,不会覆盖。

前面说到了,mark、measure 这两个函数,不会返回任何值。如果要读取标记或者测量的内容,需要通过调用 Performance 接口中的“getEntries”、“getEntriesByType”或者“getEntriesByName”函数读取。其中“getEntries”返回当前performance 对象中保存的所有标记(包括网页加载的资源)和测量结果;“getEntriesByType”函数通过类型获取对应的标记;“getEntriesByName”函数通过标记(或者测量结果)名称来获取对应的数据。这些函数的返回值是 PerformanceEntry 对象列表,包含名称、开始时间、耗时等字段。

例如,如果要获取所有的标记或者测量结果,可以通过“getEntriesByType”函数获取:

复制代码
performance.mark("start");
performance.mark("end");
performance.measure("difference", "start", "end");
var marks = performance.getEntriesByType("mark");
var measures = performance.getEntriesByType("measure");
console.log("===marks===:")
marks.forEach(function(mark) {
console.log(mark.name + ": " + mark.startTime);
})
console.log("===measures===:")
measures.forEach(function(measure){
console.log(measure.name + ": " + measure.duration)
})

在浏览器(Chrome)控制台执行后的输出为:

复制代码
===marks===:
start: 6805479.590000001
end: 6805479.74
===measures===:
difference: 0.14999999944120646

可以看见,返回的对象中,name 字段为设置的标记(测量结果)的名称,对于标记可以通过 startTime 获取标记时间(和前文提到的 now 函数一样,这里返回的时间也是相对于 navigationStart 事件),对于计算结果,可以通过 duration 字段获取计算结果。上面示例中使用的“mark”、“measure”两种类型之外,浏览器(Chrome、Firefox 等)已经支持“resource”类型。也就是说,这些浏览器已经默认帮我们测量了所有外部资源加载的耗时。对于之前示例中的 html(包含一个图片的引用),如果在浏览器的控制台执行下面的 js 代码,可以直接看见这个图片加载的耗时:

复制代码
performance.getEntriesByType("resource").forEach(function(r) {
console.log(r.name + ": " + r.duration)
})

上述代码输出(Chrome)为:

复制代码
http://cdn3.infoqstatic.com/statics_s2_20150922-
0305u1/styles/i/logo_bigger.jpg: 21.696999901905656

这个数据和 Chrome 开发者工具中网络标签页中对该请求记录的耗时完全一致。

如果要直接通过标记、测量结果名称获取数据,可以通过 getEntriesByName 函数获取。需要注意的是,该函数同样返回的是 PerformanceEntry 对象数组,需要迭代获取具体数据。

同样,Performance 接口也提供了移除标记的接口。可以通过 clearMarks 和 clearMeasures 函数,删除之前创建的标记和测量结果。这两个函数都接收一个可选的名称参数,如果传入名称,则删除指定名称的数据,否则清空标记 / 测量结果。

复制代码
performance.clearMarks();
performance.mark("start");
performance.mark("end");
var marks = performance.getEntriesByType("mark");
console.log("before clear:")
marks.forEach(function(mark) {
console.log(mark.name + ": " + mark.startTime);
})
performance.clearMarks("start");
marks = performance.getEntriesByType("mark");
console.log("after clear:")
marks.forEach(function(mark) {
console.log(mark.name + ": " + mark.startTime);
})

上述代码执行后的输出为:

复制代码
before clear:
start: 9080690.565000001
end: 9080690.575000001
after clear:
end: 9080690.575000001

也就是说,执行了performance.clearMarks("start");之后,“start”标记被清除了。

浏览计时 API

浏览计时 API 统计了一个网页从卸载当前文档开始到加载完毕这整个流程中,每个节点的时间戳。和用户计时API 不同的是,浏览器计时API 的时间,是标准的时间戳。每个节点的时间戳,都保存在 performance.timing对象中。其中包含的每个节点,可以参考下图:

(点击放大图像)

复制代码
console.log(performance.timing.domLoading);
console.log(performance.timing.domComplete);
console.log("load time: " + (performance.timing.domComplete -
performance.timing.domLoading ));

例如,可以通过获取 domComplete(DOM 构建完成)和 domLoading(DOM 开始构建)的差值,来计算构建 DOM 树消耗的时间。

除了 timing 对象中保存的各个节点加载时间戳,performance 对象中还保存了和 navigation 对象。它保存了当前页面的加载类型和重定向次数。其中,加载类型类型有:

  • TYPE_NAVIGATE(type == 0):通过点击链接、输入地址、表单提交、脚本初开启等方式加载
  • TYPE_RELOAD(type == 1):通过重新加载或者 location.reload() 操作加载
  • TYPE_BACK_FORWARD(type == 2):通过浏览器历史遍历操作加载
  • TYPE_RESERVED(type == 255):上面没有定义的其他方式

如直接打开一个页面,在控制台中执行:

console.log(performance.navigation.type);上述脚本执行后,控制台会输出 0,表示这是直接打开的一个页面。再次刷新页面,重新执行上面的 JavaScript 片段,则会输出 1,表示这是一次重新加载。

performance.timing.redirectCount 记录了当前页面经历的重定向次数。

浏览器支持

用户计时 API 已经大部分浏览器支持,如IE10+、Chrome 25+、Firefox 15+ 等,但是Safari 等浏览器还不支持。对于浏览计时API,更多的浏览器已经支持,包括Chrome、Firefox、IE9+、Safari 8+ 等等。


感谢徐川对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。

2015-10-13 18:249429

评论

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

开源一夏 | 分享一款实用的太阳能充电电路(室内光照可用)

矜辰所致

开源 电路设计 8月月更 太阳能

《数字经济全景白皮书》金融数字用户篇 重磅发布!

易观分析

金融 数字用户

近邻搜索算法浅析

得物技术

深度学习 算法 Faiss 近邻搜索 乘积量化

Java网络编程IO模型 --- BIO、NIO、AIO详解

Bug终结者

Java io 8月月更

开源一夏 | 教你快速实现“基于Docker快速构建基于Prometheus的MySQL监控系统”

知识浅谈

开源 8月月更

LP流动性挖矿DAPP系统开发丨流动性挖矿功能原理及说明

开发微hkkf5566

本周四晚19:00知识赋能第4期直播丨OpenHarmony智能家居项目之设备控制实现

OpenHarmony开发者

OpenHarmony

Python 教程之输入输出(3)—— 在 Python 中从用户那里获取多个输入

海拥(haiyong.site)

Python 8月月更

Hadoop Spark太重,esProc SPL很轻

石臻臻的杂货铺

SPL

Dva.js 新手入门指南

Susie喵~

dva 8月月更

聊天app开发——防炸麦以及节省成本的内容鉴定方法

开源直播系统源码

软件开发 语音聊天室 直播系统源码 直播源码 语音app开发

STM32+OLED显示屏制作指针式电子钟

DS小龙哥

8月月更

后台图库上传功能

CRMEB

XDR平台架构与关键技术解析

极盾科技

网络安全 信息安全 数据安全 xdr 检测响应

微信小程序获取用户手机号码

源字节1号

微信小程序 软件开发 前端开发 后端开发

Linux工具之Vim编辑器

TimeFriends

8月月更

1K字详解canal-1.1.5实时同步MySQL数据到Elasticsearch

了不起的程序猿

MySQL 数据库 程序员 Java 分布式

mysql进阶(二十四)防御SQL注入的方法总结

No Silver Bullet

MySQL SQL注入 8月月更

限流不只有计数器,带你快速了解四种经典限流算法实现

知识浅谈

8月月更

wallys/new product/MT7915/MT7975/4*radios/

wallys-wifi6

下午见!2022京东云数据库新品发布会

京东科技开发者

MySQL 数据库 云计算 安全 数据迁移

深入理解MySQL事务MVCC的核心概念以及底层原理

jiangxl

MySQL 事务 MVCC dba 签约计划第三季

浅聊缓存函数

掘金安东尼

前端 8月月更 高阶函数

ABAB-740新语法

桥下本有油菜花

SAP abap

实至名归!九章云极DataCanvas公司荣获智能制造领域多项殊荣

九章云极DataCanvas

智能制造

TiKV & TiFlash 加速复杂业务查询丨TiFlash 应用实践

PingCAP

TiDB

Sass/Scss、Less 是什么?

CRMEB

中文字体反爬,易易易易易易【Python脱敏】车车车车车车车车

梦想橡皮擦

Python 爬虫 8月月更

深入解析分布式文件系统的一致性的实现

移动云大数据

分布式系统 数据同步

浅谈SVN备份

剑雪封喉

C#/VB.NET 从PDF中提取表格

在下毛毛雨

C# .net PDF 提取表格

使用HMTL5 API监控前端性能_HTML5_金灵杰_InfoQ精选文章