在 Chrome 开发工具中在 js 堆上构建“(编译代码)”意味着什么?这是内存泄漏吗?

kat*_*kat 9 memory-leaks v8 google-chrome-devtools reactjs

我一直在尝试追踪 ReactJS Web 应用程序中的小内存泄漏。它在 10 分钟左右的时间内增加了 10-30 mb。

我使用 chrome 开发工具拍摄了 3 张堆快照:一张是在页面加载并处于稳定状态后拍摄的,一张是在执行我怀疑泄漏的操作后拍摄的,第三张是在第二次执行该操作后拍摄的。现在我正在研究快照之间正在构建的内容。

我看到了一些问题,并且正在努力修复它们,但是在我的快照之间的堆上堆积的第一大罪魁祸首是(compiled code). 我正在努力理解这代表什么,以及这是否是泄漏。

在页面完全加载并处于稳定状态后,什么会导致代码加载到内存中?这是否表明存在泄漏?

jmr*_*mrk 9

(V8 开发人员在此。)

在页面完全加载并处于稳定状态后,什么会导致代码加载到内存中?

V8 动态编译您的 JavaScript 代码。目前,它的执行管道如下所示:

  • 当您第一次加载页面时,V8 仅非常简单地查看所有 JavaScript 源代码以找出存在哪些函数以及它们的定义位置。
  • 第一次调用函数时,它会被编译为“字节码”,这是 V8 解释器可以执行的 JS 源的经过非常简单处理的版本。
  • 当 V8 观察到解释给定函数花费了一些时间时,它会将其编译为未优化的机器代码。这个编译非常快(因为没有执行任何优化),并且生成的代码比解释器快很多,但远非完美。
  • 当 V8 观察到在这样的函数上花费了更多的时间时,它最终会为其安排一个优化的编译作业。优化编译器在后台运行,花费更多时间进行优化,并生成更好的代码。一旦完成给定函数,对该函数的下一次调用就可以使用优化后的机器代码。

(这里跳过了一堆细节,但这就是要点。此外,我们继续致力于 V8,所以如果你找到五年前的文章,他们会描述类似但不同的情况;并且团队目前正在再次尝试稍微改变一下,所以这个描述可能会在适当的时候变得有些过时。一些进一步的阅读在这里。)

在页面加载期间很少有函数被编译为机器代码,这是完全正常/预期的,特别是因为在那里运行的许多代码只运行一次来​​设置东西。
一旦您开始使用页面的功能并且某些 JS 函数重复运行和/或运行更长时间,它们将被编译为机器代码,因此您将(compiled code)在堆快照中看到更多内容。

这是否表明存在泄漏?

不会。这只是表明多层 JIT 编译系统正在发挥其作用。

如果您观察到代码量永远增长,例如,每次重复某个操作时,您都会获得 X 数量的额外编译代码,并且这种增长永远不会停止,那么这听起来像是泄漏。但这不是您所描述的。 )