Che*_*ent -101 javascript performance operators
条件运算符===和赋值运算符=之间的性能是否存在差异?我正在用猫鼬写一些预保存的钩子中间件,我想知道是否有很大的速度差异:
UserSchema.pre('save', function (next) {
if (!this.isModified()) {
return next();
}
this.crm.isUpToDate = false;
next();
});
Run Code Online (Sandbox Code Playgroud)
和
UserSchema.pre('save', function (next) {
if (!this.isModified()) {
return next();
}
if (this.crm.update === true) {
this.crm.isUpToDate = false;
}
next();
});
Run Code Online (Sandbox Code Playgroud)
编辑:
感谢您的建设性意见.
基本上,它看起来并没有太大的性能差异(如上所述它可以忽略不计).感谢http://jsperf.com/测试速度的酷工具,我以前从未听说过它.
对于那些想知道代码的人,首先我在原帖中犯了一个明显的错误,然后当每个人都试图向我指出我哭了,这可能是每个人都投票的原因.
这是我在做的事情:
我有一个mongoose预保存中间件挂钩(用于mongo数据库),每次保存文档时都会运行挂钩.在保存时,我检查文档是否已更新.如果是我将其设置crmIsUpToDate为false.crmIsUpToDate当cron作业到达时,将设置为true.在cron作业到达文档之前,可以多次运行此挂钩.
我认为这不是问题的必要条件,因为问题在于进行比较===和做作业之间是否存在差异=.我甚至不应该把代码放上去,因为它确实减少了主要问题.
Chr*_*ris 45
当你有一个非引用语言(JavaScript不是)并且做一个大对象的赋值('=',导致复制操作)时,它可能是"慢"的.因此,检查是否真的需要复制操作可以节省大量时间.
但JavaScript是一种本机引用语言:
object1 = {a: 1, b: 2};
object2 = object1; // refcounting copy?
object1.a = 3; // test by modifying the first object
console.log( object2.a ); // will return 3 => refcounting
Run Code Online (Sandbox Code Playgroud)
=>所以所有赋值操作('=')都很便宜.
而且,更重要的是,您正在使用本机数据类型(bool,数字将是相同的),可能更快或至少与对象一样快.
注意:字符串不会在JavaScript中重新计算,在这种情况下它们是一个例外.
所以,现在我们已经知道这项任务很便宜.但身份检查('===')呢?
在你的代码中,你必须绕过对象this- > crm- > update- 这需要一些额外的时间.然后必须检查类型(bool)的相同性,然后检查内容(false)是否相同.
所有这些都是在程序流程中添加条件,其中具有长管道的现代CPU可能猜测分支错误地创建停顿和重新加载整个管道.这也浪费了相当多的CPU周期(尽管现代CPU在这方面相当不错).
=>这种比较('===')非常昂贵.
结论#1:
您不应该通过可以轻松避免的昂贵测试来保护廉价代码.
当代码变得更加昂贵时,测试将在最后节省时间.这导致:
结论#2:
过早优化是邪恶的!它可以使代码更难阅读,引入新的错误,使代码更大(也有利于缓存效率),...
=>只优化那些你确定在性能问题中运行的代码部分 - 然后只基于分析信息.人类在这里猜测效果是非常糟糕的......
当前的最佳答案在一个重要点上是不正确的:===与 类似=,因为它没有深入比较对象;它只是检查它们是否引用了内存中的同一个对象。(if分支是这里唯一真正的罪魁祸首)
条件运算符
===和赋值运算符之间的性能有什么区别=吗?
===不是条件运算符 -===是“严格相等比较”(或“身份”或“严格等于”)。(Javascript 的条件运算符的形式为condition ? expr1 : expr2)
前面已经介绍了赋值varName = expression非常便宜:本质上,它获取expression内存中 where 的位置,并varName指向该位置。即使expression是一个巨大的对象,也不会发生深度复制。
但在大多数情况下,严格平等比较也是如此 -expr1 === expr2将评估为true:
两个表达式都是基元,并且都具有相同的类型和相同的值(除了NaN),或者
两个表达式都是对象,对象是内存中的同一个对象。
检查两个对象表达式是否引用内存中的同一个对象非常便宜 - 它与获取对象的内存引用和具有指向该内存位置的变量(也是=如此)处于同一数量级。===不会深入比较每个嵌套的属性和值(除非您明确地使用JSON.stringifying 的两侧之类的东西这样做===,但在这种情况下,瓶颈是JSON.stringify,而不是===)
带有if分支的代码:
if (this.crm.update === true) {
this.crm.isUpToDate = false;
}
Run Code Online (Sandbox Code Playgroud)
将比普通分配慢:
this.crm.isUpToDate = false;
Run Code Online (Sandbox Code Playgroud)
因为逻辑分支很慢(相对);在===检查和=分配都相当快:
作为一般经验法则,分支比直线代码慢(在所有 CPU 和所有编程语言上)。- jmrk,V8 开发者
这与著名问题背后的问题相同:为什么处理排序数组比处理未排序数组更快?
也就是说,虽然逻辑分支确实需要额外的资源,但在现代计算机上,这种影响很少显着 - 最好争取干净、可读的代码,并且只有在确定该部分导致性能下降后才考虑更改该部分瓶颈,否则你会使代码更难阅读,因为这通常是一种难以察觉的差异。
| 归档时间: |
|
| 查看次数: |
7432 次 |
| 最近记录: |