-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Strange deoptimzations in cycles #9729
Comments
If the let k = 4;
while (k--){
const func = () => {};
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
console.log('');
[1, 2, 3, 4].forEach(() => {
const func = () => {};
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
});
console.log('');
for (let j = 1; j <= 4; j++) {
const func = () => {};
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
|
With non-empty functions that return different values, the difference remains (with less ratio, though): let k = 4;
while (k--){
const func = () => { return Math.random(); };
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
console.log('');
[1, 2, 3, 4].forEach(() => {
const func = () => { return Math.random(); };
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
});
console.log('');
for (let j = 1; j <= 4; j++) {
const func = () => { return Math.random(); };
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
|
However, if the function declaration is removed from cycles, the difference disappears: const func = () => {};
let k = 4;
while (k--){
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
console.log('');
[1, 2, 3, 4].forEach(() => {
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
});
console.log('');
for (let j = 1; j <= 4; j++) {
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
At the same time, the " const func = () => {};
[1, 2, 3, 4].forEach(() => {
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
});
console.log('');
for (let j = 1; j <= 4; j++) {
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
console.log('');
let k = 4;
while (k--){
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
|
And some more
let k = 1;
while (k--){}
for (let j = 1; j <= 4; j++) {
const func = () => {};
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
for (let j = 1; j <= 4; j++) {
const func = () => {};
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
let k = 1;
while (k--){}
let k = 1;
while (k--){}
for (let j = 1; j <= 4; j++) {
const func = () => {};
const start = Date.now();
for (let i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
k = 1;
while (k--){}
|
In the ES5 code the difference ratio is bigger: var func, start, j, i;
for (j = 1; j <= 4; j++) {
func = function () {};
start = Date.now();
for (i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
However, the var func, start, j, i, k;
for (j = 1; j <= 4; j++) {
func = function () {};
start = Date.now();
for (i = 0; i < 100000000; i++) func();
console.log(Date.now() - start);
}
k = 1;
while (k--){}
|
Issue distribution:
|
This is a pure V8 question, or possibly bug report, should be reported upstream to theml |
This is expected. We first need warm-up and only tier-up once we have a couple of cycles in the relevant function. Also note that there's only one deoptimization in forEach, and that doesn't really affect the outcome. |
In your first example, the When you remove it, it then deopts because of the The Here is a revised version that has stable performance characteristics. let start;
function before() { start = Date.now(); }
function after() { console.log(Date.now() - start); }
const func = () => {};
[1, 2, 3, 4].forEach(() => {
before();
for (var i = 0; i < 1e8; i++) func();
after();
}); |
@bmeurer, @bnoordhuis Thank you! However, how would you explain this remaining const func = () => {};
const start = Date.now();
for (var j = 1; j <= 4; j++) {
for (var i = 0; i < 1e8; i++) func();
}
console.log(Date.now() - start);
const func = () => {};
const start = Date.now();
for (var j = 1; j <= 4; j++) {
for (var i = 0; i < 1e8; i++) func();
}
console.log(Date.now() - start);
let k = 1;
while (k--){}
|
Oops. This is not the const start = Date.now();
for (var i = 0; i < 1e9; i++) ;
console.log(Date.now() - start);
const start = Date.now();
for (var i = 0; i < 1e9; i++) ;
console.log(Date.now() - start);
var k = 1;
const start = Date.now();
for (var i = 0; i < 1e9; i++) ;
console.log(Date.now() - start);
const k = 1;
const start = Date.now();
for (var i = 0; i < 1e9; i++) ;
console.log(Date.now() - start);
let k = 1;
With non-empty cycle the ratio increases from 2 to 10: const func = () => {};
const start = Date.now();
for (var i = 0; i < 1e9; i++) func ();
console.log(Date.now() - start);
var k = 1;
const func = () => {};
const start = Date.now();
for (var i = 0; i < 1e9; i++) func ();
console.log(Date.now() - start);
const k = 1;
Is this also intended or should I post a separate bug upstream? |
Reported just in case. |
@bmeurer Per #9729 (comment) - in particular, moving
|
@bnoordhuis The I'll have a look at the |
Ah, the |
Recognize Date.now() calls in the Typer and assign the proper integer type to them. See Node issue nodejs/node#9729 for more information. R=yangguo@chromium.org BUG=v8:5267 Review-Url: https://codereview.chromium.org/2528853003 Cr-Commit-Position: refs/heads/master@{#41242}
And finally, the |
Interesting, thanks. I had a more-or-less accurate mental image of the let-vs-var issue but I was looking in completely the wrong place for the |
You're welcome. I'll see if I can push a bit harder for the inlining fixes. |
Crankshaft has this highly unpredictable performance cliff around the "Unsupported phi use of const or let variable", which is due to the fact that Crankshaft refuses to do hole checks (for a couple of reasons). So ideally we should not even try to send any lexically bound variables to fullcodegen+Crankshaft, but instead give them to Ignition and TurboFan. This CL only adds the appropriate check to the AstNumbering, but doesn't remove the functionality from fullcodegen/Crankshaft yet. This would be step two in case this CL sticks. If you see any major performance regressions with this CL in the range, just revert it and ping me. See Node.js issue nodejs/node#9729 for additional information. BUG=v8:5666 R=hablich@chromium.org, mstarzinger@chromium.org, rmcilroy@chromium.org Review-Url: https://codereview.chromium.org/2525243002 Cr-Commit-Position: refs/heads/master@{#41445}
And finally with crrev.com/2525243002 |
The first iteration in cycles runs much faster than others:
It renews in another cycle with a different ratio:
It becomes more strange with
while
cycle added in the end (this cycle removes the difference in the previous cycle, but it almost doubles its run time besides):The text was updated successfully, but these errors were encountered: