吸气功能的速度与直接访问的速度

speed of getter function vs direct access

本文关键字:速度 访问 功能      更新时间:2023-09-26

我最近开始使用更多的getter函数,而不是直接访问,以使我的代码更加灵活。我很好奇这在速度方面的成本是多少。假设earth是一个对象,我们有以下父对象:

var star={}
star.planet=earth
star.getPlanet=function(){
  return this.planet
}

以下两个语句之间的速度差异是否不可忽视?

print(star.planet)
print(star.getPlanet()) 

在 V8 中:

如此短且没有上下文分配变量的函数将被内联。当然,除非已经积累了太多的内联,在这种情况下,调用仍然非常便宜,因为函数的整个执行部分适合 64 字节指令缓存行。

当您的函数在没有处于严格模式的情况下使用例如arguments或定义引用函数变量的内部函数时,就会发生上下文分配变量。另一个问题是,在 x64 上,如果调用方和被调用方不能共享相同的上下文,则无法内联函数,因此总而言之,避免像瘟疫一样闭包。

请参阅:http://jsperf.com/312319sakd 虽然看起来Firefox使用死代码消除(这令人沮丧,因为为什么要浪费时间这样做?


奖励:这个jsperf故意使getter函数在当前的V8中不可内联(通过巨大的注释,这将使函数大小启发式失败)。你可以看到,即使函数没有内联,它仍然只比直接引用道具慢 25%。

请注意,当函数无法内联时,它被视为一个黑盒,调用函数不知道其副作用,因此速度对代码高度上下文敏感。

你不需要在 JavaScript 中创建这样的冗余 getter/setters 函数。如果在稍后阶段在设置属性时需要一些验证,或者在获取属性时需要一些准备,则可以执行此操作。

var star = {
    get planet() {
        this._planet.prepare()
        return this._planet
    },
    set planet(planet) {
        if (! isPlanet(planet))
            throw Error('Not a planet')
        this._planet = planet
    }
}
star.planet = earth

。并且不更改对象的用法。