什么是更好的:创建一个新变量或将值赋给对象字段?

时间:2015-12-01 03:07:26

标签: javascript node.js performance

我想知道实施起来会更快。

我想要一个临时变量,用于函数内部的一些计算。稍后将使用attackerdefender个对象,并且应删除在其中创建的所有内容。

首先,我有一种创建临时dmg变量的方法来存储attackerdefender的损失。

                    var dmg;
                    dmg.attacker = 10;
                    dmg.defender = 10;           
                    var battle = function (dmg, attacker, defender) {
                        //Some calculations using dmg.attacker and dmg.defender.        
                    }

第二种方法是,我将attacke r和defender dmg存储在其中。如果程序的其他部分在删除attacker/defender之前捕获dmg对象,则没有问题。

                    attacker.dmg = 10;
                    defender.dmg = 10;
                    var battle = function (attacker, defender) {
                        //Some calculations using attacker.dmg and defender.dmg.
                        delete attacker.dmg;
                        delete defender.dmg;                            
                    }

那么,哪种实施会更快,为什么呢?还有其他更好的选择吗?我正在使用Node 4 LTS,它有任何我不知道的细微差别吗?

2 个答案:

答案 0 :(得分:3)

这不是性能应该成为最终指导因素的事情,特别是没有手中的剖析器。在您事后开始测量热点之前,让可维护性和生产力成为指导力量。

这就是说,正如一般的经验法则,你的状态变化和访问的局部性越大,通常它们就越快。从性能的角度来看,更多本地访问局部变量比访问更少但更全局的变量更为可取。

当地国家很快

当大量信息随时可用时,优化编译器会发挥最佳作用。分析函数的局部变量时,有效的寄存器分配和指令选择比全局变量更容易,其范围比可在任何地方修改和访问的函数范围更广。

效率的关键通常围绕从较慢但较大的内存(例如DRAM)加载到更快但更小的内存(L1缓存行然后注册)。使代码快速意味着在那些更快但更小形式的存储器(例如寄存器)内尽可能多地保持和使用频繁访问的存储器。当变量具有非常局部的作用域时,编译器更容易做到这一点,因为它不必在该作用域之外查看它是否需要将变量溢出到堆栈或者是否可以将其保留在寄存器中,例如

因此,作为一般经验法则,更喜欢具有较短范围的更多本地状态到具有更宽范围的更多全局状态。这不仅可以提高效率,还可以减少人为错误*。

*请注意,这与装配思维方式相反。在汇编中,尽可能重用寄存器有助于避免堆栈溢出。在具有变量而不是直接寄存器访问的语言中,更多本地变量帮助编译器找出它可以重用的寄存器。

具体示例

在这种特定情况下,添加成员并从关联结构中删除它们(在JS中适合这种情况的对象)往往比创建成员更昂贵,而只是将其作为一个整体丢弃。这些行:

delete attacker.dmg;
delete defender.dmg;

...特别倾向于构建一些临时对象,而只是在完成它时将其作为一个整体销毁,而不是将成员添加到更全局的对象,然后在完成后删除它们。

作为一个加号,这也应该是一个不太容易出错的错误,所以你也可以获得奖金。作为第二个加,假设attackerdefender具有相当宽的范围,创建此dmg变量的此函数将避免对这些对象的副作用,因此将是线程安全的它只处理本地状态(假设这是它正在做的而不是修改其他全局变量)。

如果你真的很挑剔,最好将攻击者伤害和后卫伤害创建为两个单独的标量,而不是聚合到一个物体中,并对这个battle函数传递两种形式的伤害。但这确实会降低代码的可读性,而且你应该只用手中的分析器来告诉你这是一个顶级的热点。

答案 1 :(得分:2)

根据下面的片段结果,第一种方法要快得多。



var dmg = {};
var battleDmg = function (dmg) {};

var start = new Date().getTime();
for(var i = 0; i < 100000; i++) {
	dmg.attacker = 10;
	dmg.defender = 10;
	battleDmg(dmg);
}
console.log('dmg:' + (new Date().getTime() - start));

var attacker = {}, defender = {};
var battleAttackerVsDefender = function (attacker, defender) {
	delete attacker.dmg;
	delete defender.dmg;                            
};

start = new Date().getTime();
for(i = 0; i < 100000; i++) {
	attacker.dmg = 10;
	defender.dmg = 10;
	battleAttackerVsDefender(attacker, defender);
}
console.log('a vs d:' + (new Date().getTime() - start));
&#13;
&#13;
&#13;

我认为这是因为在第一种情况下:

  1. 将一个参数(而不是2个参数)传递给函数
  2. 执行delete次操作(而不是2次操作)