为什么两个调用string.charCodeAt()比一个调用另一个调用的速度更快? [英] Why are two calls to string.charCodeAt() faster than having one with another one in a never reached if?

查看:85
本文介绍了为什么两个调用string.charCodeAt()比一个调用另一个调用的速度更快?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在nodejs / chrome / v8中发现了一种奇怪的行为。看来这段代码:

  var x = str.charCodeAt(5); 
x = str.charCodeAt(5);

比这快

  var x = str.charCodeAt(5); // x不大于170 
if(x> 170){
x = str.charCodeAt(5);
}

起初我可能比较实际的第二次通话比较贵,但当if块内的内容未调用 str.charCodeAt(5)时,性能与单次调用相同。



这是为什么?我最好的猜测是v8正在优化/去优化某些东西,但我不知道如何准确地解决这个问题或者如何防止这种情况发生。



这是链接到jsperf至少在我的机器上很好地演示了这种行为:






背景:我发现这个的原因是因为我试图优化 babel-parser



我测试过并且 str.charCodeAt()的速度是 str.codePointAt的两倍()所以我可以替换这段代码:

  var x = str.codePointAt(index ); 

with

  var x = str.charCodeAt(index); 
if(x> = 0xaa){
x = str.codePointAt(index);
}

但由于上述行为,第二个代码并没有给我任何性能优势。

解决方案

V8开发人员在这里。正如Bergi所指出的:不要使用微基准来告知这些决定,因为他们误导你。



看到数亿的结果每秒操作数通常意味着优化编译器能够消除所有代码,并且您正在测量空循环。你必须查看生成的机器代码,看看是否正在发生这种情况。



当我将四个片段复制到一个小的独立文件中进行本地调查时,我看到截然不同的表现结果。哪两个更接近您的真实用例?不知道。这种情况使得对这里发生的事情的进一步分析毫无意义。



作为一般经验法则,分支比直线代码慢(在所有CPU上,和使用所有编程语言)。所以(死代码消除和其他微基准测试陷阱除外)如果两次案例实际上比两个如果案件中的任何一个都快,我不会感到惊讶。也就是说,调用 String.charCodeAt 很可能足以抵消这种影响。


I discovered a weird behavior in nodejs/chrome/v8. It seems this code:

var x = str.charCodeAt(5);
x = str.charCodeAt(5);

is faster than this

var x = str.charCodeAt(5); // x is not greater than 170
if (x > 170) {
  x = str.charCodeAt(5);
}

At first I though maybe the comparison is more expensive than the actual second call, but when the content inside the if block is not calling str.charCodeAt(5) the performance is the same as with a single call.

Why is this? My best guess is v8 is optimizing/deoptimizing something, but I have no idea how to exactly figure this out or how to prevent this from happening.

Here is the link to jsperf that demonstrates this behavior pretty well at least on my machine: https://jsperf.com/charcodeat-single-vs-ifstatment/1


Background: The reason i discovered this because I tried to optimize the token reading inside of babel-parser.

I tested and str.charCodeAt() is double as fast as str.codePointAt() so I though I can replace this code:

var x = str.codePointAt(index);

with

var x = str.charCodeAt(index);
if (x >= 0xaa) {
  x = str.codePointAt(index);
}

But the second code does not give me any performance advantage because of above behavior.

解决方案

V8 developer here. As Bergi points out: don't use microbenchmarks to inform such decisions, because they will mislead you.

Seeing a result of hundreds of millions of operations per second usually means that the optimizing compiler was able to eliminate all your code, and you're measuring empty loops. You'll have to look at generated machine code to see if that's what's happening.

When I copy the four snippets into a small stand-alone file for local investigation, I see vastly different performance results. Which of the two are closer to your real-world use case? No idea. And that kind of makes any further analysis of what's happening here meaningless.

As a general rule of thumb, branches are slower than straight-line code (on all CPUs, and with all programming languages). So (dead code elimination and other microbenchmarking pitfalls aside) I wouldn't be surprised if the "twice" case actually were faster than either of the two "if" cases. That said, calling String.charCodeAt could well be heavyweight enough to offset this effect.

这篇关于为什么两个调用string.charCodeAt()比一个调用另一个调用的速度更快?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆