简体   繁体   English

为什么隐式转换比JS中的显式快得多?隐式铸造是一种好的做法吗?

[英]Why is implicit casting is much faster than explicit in JS? Is implicit casting a good practice?

I know it is cleaner and nicer to cast types like String(1234) and Number("1234") , but I just tried to benchmark alternative ways of doing the same thing, specifically "" + 1234 // -> "1234" and - - "1234" // -> 1234 . 我知道像String(1234)Number("1234")这样的类型是更干净和更好,但我只是尝试对同样的事情进行基准测试,特别是"" + 1234 // -> "1234"- - "1234" // -> 1234

The results were quite surprising (for me). 结果非常令人惊讶(对我而言)。 I iterated over each way 100,000,000 times in Chrome. 我在Chrome中每次迭代100,000次。

I used this simple code. 我使用了这个简单的代码。

var then = Date.now(); 
for (var i = 0; i < 100000000; ++i) {
    var a = - - "1234";
}; 
console.log(Date.now() - then);

Number("1234") took 2351 ms whereas - - "1234" took only 748 ms. Number("1234")花费了2351毫秒而- - "1234"只花了748毫秒。

Similarly for the other way around, String(1234) took 3701 ms whereas "" + 1234 took only 893 ms. 类似地,换句话说, String(1234)花了3701 ms,而"" + 1234只花了893 ms。

The difference is surprisingly huge. 差异非常大。

My questions are: What makes the explicit casting so much slower than implicit? 我的问题是:是什么使得显式转换比隐式更慢? My intuition tells me it should be the other way around. 我的直觉告诉我它应该是另一种方式。

Is it a good practice to use implicit casting? 使用隐式强制转换是一种好习惯吗? Especially the hacky - - "1234" ? 特别是hacky - - "1234" Are there nicer alternatives? 还有更好的选择吗?

PS: I just tried the same in Firefox. PS:我在Firefox中尝试过同样的方法。 It was about 500 times slower (but still the implicit conversion was much faster). 它大约慢了500倍(但隐式转换仍然快得多)。 What is going on? 到底是怎么回事? Is it connected to branch prediction or something similar? 它是否与分支预测或类似的东西相关联? I guess I am benchmarking wrong. 我想我的基准测试错了。

If you instead of using a constant, if you use i instant then the result will be a quite different: 如果您不使用常量,如果您使用i instant,那么结果将完全不同:

console.time('a');
for (var i = 0; i < 1e7; ++i) {
    var a = String(i);
}; 
console.timeEnd('a');
console.time('b');
for (var i = 0; i < 1e7; ++i) {
    var a = "" + i;
}; 
console.timeEnd('b');

Output: 输出:

a: 1062.192ms
b: 884.535ms

Note I have to remove a power of 10 as well. 注意我也必须删除10的幂。 100000000 === 1e8 And I uses 1e7 . 100000000 === 1e8我使用1e7

This suggests that there is happening a lot of optimization under the hood when working with a constant as in your benchmark. 这表明,在基准测试中使用常量时会发生很多优化。

And now Number(...) seems to be faster: 而现在Number(...)似乎更快:

console.time('a');
for (var i = 0; i < 1e7; ++i) {
    var a = - - ("" + i);
}; 
console.timeEnd('a');
console.time('b');
for (var i = 0; i < 1e7; ++i) {
    var a = Number("" + i);
}; 
console.timeEnd('b');

Output: 输出:

a: 2010.903ms
b: 1557.735ms

In theory, use of the unary + and - operators should be faster than calling Number and String since they use the internal ToNumber and ToString methods to convert the operands to number Type, whereas Number and String require the additional overhead of a function call. 理论上,使用一元+-运算符应该比调用NumberString更快,因为它们使用内部ToNumberToString方法将操作数转换为数字Type,而NumberString需要函数调用的额外开销。

However, theory doesn't always match practice as it's likely very simple to optimise Number(x) to +x , or vice versa, which ever the compiler thinks is faster. 但是,理论并不总是与实践相匹配,因为将Number(x)优化为+x可能非常简单,反之亦然,编译器认为这种算法更快。

What makes the explicit casting so much slower than implicit? 是什么让显式转换比隐式更慢? My intuition tells me it should be the other way around. 我的直觉告诉我它应该是另一种方式。

As always, the results you get in a particular version of a browser don't necessarily apply to other browsers or even other versions of the same browser. 与往常一样,您在特定版本的浏览器中获得的结果不一定适用于其他浏览器甚至同一浏览器的其他版本。 In theory, explicit conversion should be slower, but I wouldn't depend on that across implementations. 理论上,显式转换应该更慢,但我不会依赖于实现。

Is it a good practice to use implicit casting? 使用隐式强制转换是一种好习惯吗? Especially the hacky - - "1234"? 特别是hacky - - “1234”? Are there nicer alternatives? 还有更好的选择吗?

That should be -'1234' and I would say "no" since the - operator converts it's argument to Number anyway, there is never a need to write x - -y . 这应该是-'1234' ,我会说“不”,因为-运算符将它的参数转换为数字无论如何,从来没有必要写x - -y

It's much more common to use unary + for conversion in conjunction with the addition operator + , and in most circumstances it's equally clear to write +x or Number(x) . 与加法运算符+一起使用一元+进行转换更常见,在大多数情况下,写+xNumber(x)也同样清楚。 So use: 所以使用:

x + +y

and save some typing. 并节省一些打字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM