8

据我所知,脚本是在 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>

我们将在控制台中看到下载、解析和执行 js 的总时间。我们如何排除解析时间?只需添加类似的文件,但所有代码都已注释掉。或多或少,这种技术应该有效。

问题是这不起作用=)

我优化了该代码,将执行时间从 90 毫秒减少到 25 毫秒,但 Chrome 的时间约为 100±10 毫秒,Firefox 的时间约为 160±15 毫秒。

好的,我知道我可以使用分析器,但问题是:“如何正确测量 js 解析时间”以及我测量了什么。Research.reverse-engineering 非常有趣,但也许有人深入了解该领域。

4

5 回答 5

6

您无法单独使用 Web API 准确测量脚本解析时间,而与执行时间无关。不同的浏览器在解析时有不同的策略,其中一些会随着脚本的执行而逐步解析,甚至在假设一段代码不太可能立即执行的情况下进行“部分解析”(例如一个函数这不是 IIFE,请参阅optimize-js README 中的一些详细信息)。

使用单独<script>的标签是至少捕获解析和执行时间的最准确方法。我将对您的代码段进行的唯一修改是:

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

请注意高精度用户计时 API的使用,作为额外的奖励,它将在 Chrome/Edge/IE 开发工具(如果您愿意,还可以使用 Windows Performance Analyzer 和 WebPageTest 等工具)中显示可视化。

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

于 2018-07-11T20:34:58.503 回答
4

我知道这是一个老问题,但我在自己寻找解决方案时遇到了这个问题。您可以使用您选择的浏览器中的开发工具来查看此内容,但如果您想在代码中执行此操作,这是我最终使用的方法。

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

请记住,这将<script>在当前 DOM 上下文中执行您正在分析的内容。所以在下面的例子中:jQuery即使脚本被删除,仍然可以在全局范围内访问。该脚本可以扩展以完成所有这些操作<iframe>以隔离它。

function scriptLoadParseDuration(url) {
  var start;
  var script = document.createElement('script');
  
  // <script> must be attached to the document to actually load the file
  document.querySelector('html').appendChild(script);
  
  // Calculate load/parse duration once script has loaded
  script.addEventListener('load', function scriptLoad() {   
    // Calculate load/parse duration
    console.log('Duration: ' + (Date.now() - start) + 'ms');
    
    // Remove <script> from document
    script.parentElement.removeChild(script);
  }, false);
  
  // Get current time in milliseconds
  start = Date.now();
  
  // Setting the `src` starts the loading. Math.random is used to make sure it is an uncached request
  script.src = url + '?' + Math.floor(Math.random() * 9e9);
}

var url = 'https://code.jquery.com/jquery-3.0.0.min.js';

scriptLoadParseDuration(url);

这是一个示例,显示删除jQuery后仍在全局范围内。<script>

function scriptLoadParseDuration(url) {
  var start;
  var script = document.createElement('script');
  
  console.log('`jQuery` before attaching: ' + typeof jQuery);
  
  // <script> must be attached to the document to actually load the file
  document.querySelector('html').appendChild(script);
  
  // Calculate load/parse duration once script has loaded
  script.addEventListener('load', function scriptLoad() {   
    // Calculate load/parse duration
    console.log('Duration: ' + (Date.now() - start) + 'ms');

    console.log('`jQuery` once attached: ' + typeof jQuery);
    // Remove <script> from document
    script.parentElement.removeChild(script);
    console.log('`jQuery` after detach: ' + typeof jQuery);
  }, false);
  
  // Get current time in milliseconds
  start = Date.now();
  
  // Setting the `src` starts the loading. Math.random is used to make sure it is an uncached request
  script.src = url + '?' + Math.floor(Math.random() * 9e9);
}

var url = 'https://code.jquery.com/jquery-3.0.0.min.js';

scriptLoadParseDuration(url);

于 2016-07-07T18:44:29.923 回答
2

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

于 2013-03-12T09:14:30.620 回答
1

Chrome DevTools 实际上有一个隐藏标志,显示 V8 解析和编译时间!

https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/javascript-startup-optimization#parsecompile

结果如下所示:

在此处输入图像描述

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

分步指南(蓝色部分)

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

享受!

于 2019-11-19T22:18:38.203 回答
0

非常老的问题,答案相对较新。

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

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

在 HTML5Rocks 上使用 Performance API有一个很好的指南,而不是Date.now()用于window.performance.now()测量。

于 2017-03-31T21:46:46.317 回答