javascript - 浏览器是否在每个页面加载时解析 javascript?

标签 javascript browser-cache javascript-engine

浏览器(IE 和 Firefox)是否会在每次页面刷新时解析链接的 javascript 文件?

他们可以缓存文件,所以我猜他们不会每次都尝试下载它们,但由于每个页面本质上是独立的,我希望他们能够拆除任何旧代码并重新解析它。

这是低效的,虽然完全可以理解,但我想知道现代浏览器是否足够聪明,可以避免站点内的解析步骤。我在考虑网站使用 javascript 库(如 ExtJS 或 jQuery 等)的情况。

最佳答案

这些是我能够挖掘的细节。首先值得注意的是,虽然 JavaScript 通常被认为是在 VM 上解释和运行,但现代解释器并非如此,它们倾向于将源代码直接编译成机器代码(IE 除外)。


Chrome:V8 引擎

V8 有一个编译缓存。这使用源的哈希存储已编译的 JavaScript,最多可用于 5 个垃圾收集。这意味着两个相同的源代码将在内存中共享一个缓存条目,无论它们是如何包含的。重新加载页面时不会清除此缓存。

Source


更新 - 2015 年 3 月 19 日

Chrome 团队发布了 details about their new techniques for JavaScript streaming and caching .

  1. 脚本流

Script streaming optimizes the parsing of JavaScript files. [...]

Starting in version 41, Chrome parses async and deferred scripts on a separate thread as soon as the download has begun. This means that parsing can complete just milliseconds after the download has finished, and results in pages loading as much as 10% faster.

  1. 代码缓存

Normally, the V8 engine compiles the page’s JavaScript on every visit, turning it into instructions that a processor understands. This compiled code is then discarded once a user navigates away from the page as compiled code is highly dependent on the state and context of the machine at compilation time.

Chrome 42 introduces an advanced technique of storing a local copy of the compiled code, so that when the user returns to the page the downloading, parsing, and compiling steps can all be skipped. Across all page loads, this allows Chrome to avoid about 40% of compile time and saves precious battery on mobile devices.


Opera : Carakan 引擎

In practice this means that whenever a script program is about to be compiled, whose source code is identical to that of some other program that was recently compiled, we reuse the previous output from the compiler and skip the compilation step entirely. This cache is quite effective in typical browsing scenarios where one loads page after page from the same site, such as different news articles from a news service, since each page often loads the same, sometimes very large, script library.

因此,JavaScript 在页面重新加载时被缓存,对同一脚本的两个请求不会导致重新编译。

Source


Firefox : SpiderMonkey 引擎

SpiderMonkey 使用 Nanojit 作为其原生后端,即 JIT 编译器。编译机器码的过程可以看here .简而言之,它似乎在加载脚本时重新编译它们。但是,如果 we take a closer lookNanojit 的内部,我们看到用于跟踪编译的更高级别的监视器 jstracer 在编译过程中可以过渡三个阶段,从而为 Nanojit 提供了一个好处:

The trace monitor's initial state is monitoring. This means that spidermonkey is interpreting bytecode. Every time spidermonkey interprets a backward-jump bytecode, the monitor makes note of the number of times the jump-target program-counter (PC) value has been jumped-to. This number is called the hit count for the PC. If the hit count of a particular PC reaches a threshold value, the target is considered hot.

When the monitor decides a target PC is hot, it looks in a hashtable of fragments to see if there is a fragment holding native code for that target PC. If it finds such a fragment, it transitions to executing mode. Otherwise it transitions to recording mode.

这意味着对于 hot 代码片段,本地代码被缓存。这意味着不需要重新编译。 目前尚不清楚这些散列的 native 部分是否在页面刷新之间保留。但我会假设他们是。 如果有人能找到支持这一点的证据,那就太好了。

编辑: 有人指出,Mozilla 开发人员 Boris Zbarsky 曾表示 Gecko 尚未缓存已编译的脚本。取自 this SO answer .


Safari : JavaScriptCore/SquirelFish 引擎

我认为这个实现的最佳答案已经been given by someone else .

We don't currently cache the bytecode (or the native code). It is an
option we have considered, however, currently, code generation is a
trivial portion of JS execution time (< 2%), so we're not pursuing
this at the moment.

这是由 Maciej Stachowiak 撰写的,Safari 的主要开发者。所以我认为我们可以认为这是真的。

我找不到任何其他信息,但您可以阅读有关最新 SquirrelFish Extreme 引擎的速度改进的更多信息here ,或浏览源代码here如果您喜欢冒险。


IE:脉轮引擎

在此字段中没有关于 IE9 的 JavaScript 引擎 (Chakra) 的当前信息。 如果有人知道,请发表评论。

这是相当非官方的,但对于 IE 的旧引擎实现,Eric Lippert (a MS developer of JScript) 在博客回复 here 中指出那:

JScript Classic acts like a compiled language in the sense that before any JScript Classic program runs, we fully syntax check the code, generate a full parse tree, and generate a bytecode. We then run the bytecode through a bytecode interpreter. In that sense, JScript is every bit as "compiled" as Java. The difference is that JScript does not allow you to persist or examine our proprietary bytecode. Also, the bytecode is much higher-level than the JVM bytecode -- the JScript Classic bytecode language is little more than a linearization of the parse tree, whereas the JVM bytecode is clearly intended to operate on a low-level stack machine.

这表明字节码不会以任何方式持久化,因此字节码不会被缓存。

关于javascript - 浏览器是否在每个页面加载时解析 javascript?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1096907/

相关文章:

javascript - 检测 HTML 元素是否分配了 javascript 函数

safari - webkit 中的 safari javascript 引擎

javascript - 添加更改已保存的 Javascript 弹出窗口

javascript - 发布新的 Vue 应用程序版本时清除 chrome 中的缓存

javascript - 使用 jQuery 检查值数组

asp.net - 禁用整个 ASP.NET 网站的浏览器缓存

javascript - 在浏览器中手动缓存 SWF/SWC - 模仿 Adob​​e 的签名 SWZ?

javascript - 修改 Chrome 自带的 V8 JavaScript 引擎

Javascript点击按钮,反函数

javascript - 表上的行渲染事件