console.time与window.performance.measure计时结果差异原因
免责声明:受所使用运行库的性能问题影响,以下代码片段在多数浏览器中可能运行缓慢甚至出现无响应卡死的情况,但该片段可复现暂未排查出根因的异常现象。
问题描述
- 核心疑问:运行下述代码时,
console.time与window.performance.measure两个前端计时API的统计结果为何存在极大差异? - 异常现象:
console.time统计输出的是毫秒级的极短耗时,而window.performance.measure返回的耗时约为40秒。

复现代码
import { unified } from "unified"; import remarkParse from "remark-parse"; import remarkRehype from "remark-rehype"; import rehypeStringify from "rehype-stringify"; const sourceMarkdown = ` 1${" ".repeat(75000)}2 `; document.getElementById("source").innerHTML = sourceMarkdown; try { console.time("unified-pipeline"); window.performance.mark("unified-pipeline"); unified() .use(remarkParse) .use(remarkRehype) .use(rehypeStringify) .process(sourceMarkdown) .then((file) => { document.getElementById( "result" ).contentWindow.document.body.innerHTML = String(file); console.timeEnd("unified-pipeline"); console.log(window.performance.measure("unified-pipeline")); }); } catch (err) { document.getElementById("error").innerHTML = err; }
核心原因
两个结果差异的根本原因是你对window.performance.measure的调用方式完全错误:
- 你只在流程启动前打了一个名为
unified-pipeline的mark,调用measure时只传了名称参数,没有指定测量的起点和终点。按照API标准,单参数调用performance.measure(name)时,默认从页面加载的时间原点(也就是页面刚开始导航的时刻)开始计时,到调用measure的瞬间停止,根本不会自动匹配你之前打的同名mark当起点。你测出来的40秒是页面从打开到处理完成的总时长,包含了模块加载、脚本初始化等所有前置耗时,根本不是unified管道的运行时间。 console.time和console.timeEnd是按键名严格配对的计时器,从你调用console.time的瞬间开始计时,到调用同名console.timeEnd时停止,本身计时逻辑没有问题,它统计的才是你写的这段流程从启动到回调执行的耗时。
正确写法
要让performance.measure的统计范围和console.time一致,必须明确打起止两个mark,调用measure时手动指定起止点:
try { console.time("unified-pipeline"); // 单独打起点标记,不要和measure同名避免混淆 window.performance.mark("unified-pipeline-start"); unified() .use(remarkParse) .use(remarkRehype) .use(rehypeStringify) .process(sourceMarkdown) .then((file) => { document.getElementById("result").contentWindow.document.body.innerHTML = String(file); // 流程执行完先打终点标记 window.performance.mark("unified-pipeline-end"); // 明确指定起止点生成测量结果 const measureResult = window.performance.measure( "unified-pipeline", "unified-pipeline-start", "unified-pipeline-end" ); console.timeEnd("unified-pipeline"); console.log(measureResult); }); } catch (err) { document.getElementById("error").innerHTML = err; }
补充说明
如果你改完measure用法后,还是碰到页面卡几十秒但两个API统计的耗时都很短的情况,属于正常现象:
- unified的处理逻辑核心是同步执行的,跑完才会把promise设为完成状态触发then回调;
- 你构造的测试用例里有75000个连续空格,塞到iframe之后,浏览器渲染引擎做文本布局、换行计算的时候会触发极端性能问题,这部分工作是渲染进程做的,不属于JS脚本执行范畴,不会被JS层的计时API统计到,但会阻塞主线程导致页面无响应。
内容的提问来源于stack exchange,提问作者42shadow42
相关产品推荐
相关产品推荐

