Javascript 如何度量脚本执行和*解析*时间?

Javascript 如何度量脚本执行和*解析*时间?,javascript,profiling,Javascript,Profiling,据我所知,脚本是在javascript中同步下载和执行的。 因此,如果我们编写以下代码: <script type='text/javascript'>console.time('core')</script> <script type='text/javascript' src="guicore.js"></script> <script type='text/javascript'>console.timeEnd('core')&l

据我所知,脚本是在javascript中同步下载和执行的。 因此,如果我们编写以下代码:

<script type='text/javascript'>console.time('core')</script>
<script type='text/javascript' src="guicore.js"></script>
<script type='text/javascript'>console.timeEnd('core')</script>
console.time('core'))
console.timeEnd('core'))
我们将在控制台中看到下载、解析和执行js的总时间。 如何排除解析时间?只需添加类似的文件,但所有代码都已注释掉。或多或少,这项技术应该是可行的

问题是这根本不起作用=)

我优化了代码,将执行时间从90ms减少到25ms,但Chrome和Firefox的执行时间分别为~100±10ms和~160±15ms


好的,我知道我可以使用profiler,但问题是:“如何正确测量js解析时间”以及我测量了什么。研究。反向工程非常有趣,但可能有人对该领域有深入了解。

打开Chrome并打开开发工具,转到“时间线”选项卡。如果你按下记录按钮(填在圆圈中,左下角),然后重新加载页面,它会给你一个相当详细的时间线,分解为特定类型的活动(发送请求、解析、评估),时间缩短到微秒。

我知道这是一个老问题,但我自己在寻找解决方案时遇到了它。您可以在自己选择的浏览器中使用dev工具来查看这一点,但是如果您想在代码中这样做,这就是我最终使用的方法

下面的
scriptLoadParseDuration
函数将获取
.js
文件的URL,将其放入
元素,并将加载/解析持续时间记录到控制台

请记住,这将执行您在当前DOM上下文中分析的
。因此,在下面的示例中:
jQuery
在全局范围内仍然可以访问,即使脚本已被删除。脚本可以扩展为在
中执行所有这些操作,以隔离它

函数scriptLoadParseDuration(url){
var启动;
var script=document.createElement('script');
//必须附加到文档才能实际加载文件
document.querySelector('html').appendChild(脚本);
//加载脚本后计算加载/分析持续时间
script.addEventListener('load',函数scriptLoad(){
//计算加载/解析持续时间
log('Duration:'+(Date.now()-start)+'ms');
//从文档中删除
script.parentElement.removeChild(脚本);
},假);
//以毫秒为单位获取当前时间
开始=日期。现在();
//设置'src'开始加载。Math.random用于确保它是未缓存的请求
script.src=url+'?'+Math.floor(Math.random()*9e9);
}
var url='1〕https://code.jquery.com/jquery-3.0.0.min.js';

scriptLoadParseDuration(url)非常老的问题,有一个相对新的答案

Date.now()
返回毫秒精度的时间戳。要使应用程序以60FPS的速度运行,它必须每16ms更新一次帧。我们的毫秒计可能不够精确

在现代JS浏览器中引入了,这允许浮点时间戳精确到微秒


不要使用
Date.now()
而使用
window.performance.now()
进行测量,而是有一个很好的使用指南。

您无法单独使用web API准确地测量脚本解析时间,而不依赖于执行时间。不同的浏览器在进行解析时有不同的策略,其中一些浏览器会随着脚本的执行而逐步解析,甚至在假定代码块不可能立即执行的情况下进行“部分解析”(例如,非IIFE的函数,请参阅一些详细信息)

使用单独的
标记是至少捕获解析和执行时间的最准确的方法。我对您的代码段所做的唯一修改如下:

<script>
  performance.mark('start');
</script>
<script src="myscript.js"></script>
<script>
  performance.mark('end');
  performance.measure('total', 'start', 'end');
</script>

性能。标记(“开始”);
性能。标记(“结束”);
绩效。衡量标准(“总计”、“开始”、“结束”);
注意高精度的使用,作为额外的好处,它将在Chrome/Edge/IE开发工具(以及Windows Performance Analyzer和WebGetTest等工具,如果您愿意的话)中显示可视化效果


从技术上讲,第三个
是不必要的,因为您只需将标记/度量值附加到第二个脚本的末尾即可。但是第一个
对于捕获所有解析时间来说肯定是必要的。您可以在开发工具中验证标记/度量值是否包含所有初始解析和执行时间。

Chrome开发工具实际上有一个显示V8解析和编译时间的隐藏标志

结果如下:

下面蓝色部分的文档中还提供了快速指南:

启用该功能后,您可以分析一个页面,然后单击Chrome DevTools中性能选项卡上的“自底向上”选项卡,然后确保“按活动分组”,现在应该可以看到编译和解析时间了


享受吧

注释掉的代码块与按照您自己的方法编写的未注释代码(正如您发现的)完全不同,在guicore.js的第一行中进行另一个度量如何?应该在解析后立即执行。您是否尝试过在Chrome中使用时间线视图?它将下载时间和评估时间分开是的,看起来像是Chrome同时获取多个js文件(但在执行开始之前甚至不向编译器提供数据)。不过我还是找不到时间。可能太小了。我认为实际JS的解析时间包含在“评估脚本”部分中。有一个解析事件,但我认为这是针对HTMLwell的,我可以正常地测量执行时间,并使用调用2次的
main
方法。然后使用普通算术进行计算。脚本
load
事件是在脚本执行后触发的,因此此答案不正确-它仍将包括两个PAR