何时在Node.js V8中分配和编译闭包?

Rob*_*cks 1 javascript performance v8 node.js

根据我目前关于VM及其行为的假设,我认为每次定义被击中时都会分配和编译闭包; 与在闭包之外声明的函数相比,这些函数被分配和编译一次(因为它们被放置在某个地方,它们的定义只被命中一次).这个假设是否正确?

因此,如果我有一个闭包socket.on('data', function (data) {...}),V8 每次在套接字收到数据时都会分配新内存(并可能重新编译)闭包?

Ber*_*rgi 5

我想每次关闭定义时都会分配和编译闭包

并不是的.闭包编译一次,但每次定义时都会分配.最重要的是,您必须区分分配和编译.

  • 即使函数在不同环境中多次实例化,每个函数的代码(即源代码中的相同位置)也只编译一次.
    在每个实例化上编译都是没有意义的,就像为每一个调用编译都没有意义一样(但是,这实际上就是"解释器"的作用,并且边界是流动的,例如对于不是在时间之前发生的惰性编译第一个电话).
    如果代码成为优化候选者,或者如果优化失败并且必须进行去优化,则可能会再次编译代码(使用较慢但更复杂的编译器); 但这是重点.

  • 当命中其定义时,每个函数都被分配/实例化,这与本地函数(嵌套在其他函数中)特别相关.
    然而,非闭包函数的分配成本为零,因为不需要存储环境指针,所以不需要实例对象.

因此,如果我有一个闭包socket.on('data', function (data) {...}),V8每次在套接字收到数据时都会分配新内存(并可能重新编译)闭包?

不是function (data) {…},它只被实例化一次并传递给on调用.

但是,是的,如果你有一个在部件中实例化的闭包,那么每次收到数据并调用处理程序时,它将分配一些内存.但是没有必要担心这一点,内存分配便宜且快速.

如果您正在寻找技术细节,我建议您阅读http://mrale.ph/blog/2012/09/23/grokking-v8-closures-for-fun.html(即使它已经有几年了).