最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why are two calls to string.charCodeAt() faster than having one with another one in a never reached if? - Stack Ove

programmeradmin3浏览0评论

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 parison 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:


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.

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 parison 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./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.

Share Improve this question edited Jan 13, 2019 at 19:12 danez asked Jan 13, 2019 at 7:23 danezdanez 1,7091 gold badge12 silver badges15 bronze badges 6
  • In Firefox your second option is faster then the first one (for Latin characters). Looks like something is buggy in V8. – Dmitry Commented Jan 13, 2019 at 8:24
  • Is it var or const? Is it charCodeAt or codePointAt? The snippets in your question and those in your jsperf screenshot do totally different things. – Bergi Commented Jan 13, 2019 at 9:57
  • Yes, var y = str; (where y is never used afterwards) can trivially be recognised as dead code, and so is the side-effect-free parison in the condition of an empty if statement. – Bergi Commented Jan 13, 2019 at 10:00
  • 2 If you are optimising babel-parser, then use that as a proper benchmark, instead of trying to do micro-benchmarks. – Bergi Commented Jan 13, 2019 at 10:01
  • Your first code block is a TypeError in any plying environment. You can't assign to a const other than in the (required) initializer. – T.J. Crowder Commented Jan 13, 2019 at 10:35
 |  Show 1 more ment

1 Answer 1

Reset to default 10

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 piler 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.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论