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
Rollup version 2.53.2 uses substantially more memory than 2.53.1 #4181
Comments
Cannot reproduce maximum resident memory size increase between v2.53.1 and v2.53.2 on macOS building the latest version of rollup from sources (ea96ab0), but it is evident that node v14 uses considerably more memory than node v12 or node v16: node-v12 + rollup v2.53.1 -> avg 22.10 real, 1136295936 max res
node-v14 + rollup v2.53.1 -> avg 21.96 real, 1423980544 max res
node-v16 + rollup v2.53.1 -> avg 22.15 real, 1081286656 max res
node-v12 + rollup v2.53.2 -> avg 22.10 real, 1143720960 max res
node-v14 + rollup v2.53.2 -> avg 22.02 real, 1413613568 max res
node-v16 + rollup v2.53.2 -> avg 22.06 real, 1065199616 max res
|
Maybe prettier/prettier has same problem. See prettier/prettier#11217. The CI has failed because of memory problem when building Also I've created the repository to reproduce the bug https://github.com/sosukesuzuki-sandbox/rollup-2.53.2-bug-reproduce |
Thanks for the succinct reproduction. The problem was isolated to 7c014fb. It occurs with rollup The following patch will avoid the JavaScript heap out of memory failure:
at the expense of a test regression. That code was changed to allow Using rollup 2.53.2:
Regression can be seen in rollup 2.53.2 with the patch above:
The line in question in
|
Here's a fix for the heap memory issue with no test regressions. Please try it out. --- a/src/ast/scopes/TrackingScope.ts
+++ b/src/ast/scopes/TrackingScope.ts
@@ -1,6 +1,10 @@
import { AstContext } from '../../Module';
+import BlockStatement from '../nodes/BlockStatement';
import Identifier from '../nodes/Identifier';
+import VariableDeclaration from '../nodes/VariableDeclaration';
+import VariableDeclarator from '../nodes/VariableDeclarator';
import { ExpressionEntity } from '../nodes/shared/Expression';
+import { NodeBase } from '../nodes/shared/Node';
import LocalVariable from '../variables/LocalVariable';
import BlockScope from './BlockScope';
@@ -14,6 +18,18 @@ export default class TrackingScope extends BlockScope {
isHoisted: boolean
): LocalVariable {
this.hoistedDeclarations.push(identifier);
- return super.addDeclaration(identifier, context, init, isHoisted);
+
+ let parent, grandparent;
+ if (
+ init instanceof NodeBase &&
+ (parent = init.parent) instanceof VariableDeclarator &&
+ (grandparent = parent.parent) instanceof VariableDeclaration &&
+ grandparent.kind === 'var' &&
+ !(grandparent.parent instanceof BlockStatement)
+ ) {
+ return super.addDeclaration(identifier, context, init, isHoisted);
+ }
+
+ return this.parent.addDeclaration(identifier, context, init, isHoisted);
}
} Latest git (ea96ab0) with patch:
which is comparable with rollup v2.53.1:
@lukastaegert I'll leave this with you. I wasn't able to construct a reduced test case. Perhaps you can create a more elegant fix for block-less |
By the way, the function
EE(b){if(rN.Uint8Array)var
c=new(rN.Uint8Array)(b.l);else
var
c=new
Array(b.l);var
e=b.c,d=e.length,a=0;for(;a<d;a++)c[a]=e.charCodeAt(a);for(d=b.l;a<d;a++)c[a]=0;b.c=c;b.t=4;return c} function EE(b) {
if (rN.Uint8Array) var c = new rN.Uint8Array(b.l);
else var c = new Array(b.l);
var e = b.c,
d = e.length,
a = 0;
for (; a < d; a++) c[a] = e.charCodeAt(a);
for (d = b.l; a < d; a++) c[a] = 0;
b.c = c;
b.t = 4;
return c;
} The package just happened to avoid the corner case in the test case above. |
There is a regression in latest release, which caused a OOM. Issue: rollup/rollup#4181, Probably this PR rollup/rollup#4178 caused a regression.
There is a regression in latest release, which caused a OOM. Issue: rollup/rollup#4181, Probably this PR rollup/rollup#4178 caused a regression.
Looking into this now |
So at the core of the problem we have that in some cases, up to 76000 variables are hoisted across a single if-statement. The nature of the tracking scope is that I "remembers" which variables are hoisted across it. The problem is that the change in question implicitly used a "double declaration" to mark those variables as "untracked". However those double declarations where also picked up by tracking scopes further out, blowing up some arrays tremendously. I think the answer here must be to question the use of double declarations for this purpose in general, I will think about something better. I think the problem existed to some limited extent even before the version in question. |
Although the fix in #4181 (comment) works for #4181, another large heap size increase not addressed by the patch has existed since 6260def - even with switch(x){ default: var x=1;
switch(x){ default: var x=2;
switch(x){ default: var x=3;
switch(x){ default: var x=4;
switch(x){ default: var x=5;
switch(x){ default: var x=6;
switch(x){ default: var x=7;
switch(x){ default: var x=8;
switch(x){ default: var x=9;
switch(x){ default: var x=10;
switch(x){ default: var x=11;
switch(x){ default: var x=12;
switch(x){ default: var x=13;
switch(x){ default: var x=14;
switch(x){ default: var x=15;
switch(x){ default: var x=16;
switch(x){ default: var x=17;
switch(x){ default: var x=18;
switch(x){ default: var x=19;
switch(x){ default: var x=20;
switch(x){ default: var x=21;
switch(x){ default: var x=22;
switch(x){ default: var x=23;
switch(x){ default: var x=24;
switch(x){ default: var x=25;
switch(x){ default: var x=26;
switch(x){ default: var x=27;
switch(x){ default: var x=28;
switch(x){ default: var x=29;
switch(x){ default: var x=30;
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
console.log(x); The |
There's that, but there may be some |
I have created a tentative fix here #4183, maybe this example can serve as a good test case. |
@kzc Thanks a lot for the triage work and concise test case! |
So to sum up what the root of the problem was:
So in hindsight, the use of fake declarations was easy but probably not the wises of choices. The fix now imperatively sets a flag to deoptimize the variable without using an additional declaration. |
fwiw, this is of no consequence, but here's an amusing test case solved by #4183. Only a single
Again, this is not important - feel free to ignore: --- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7 +7 @@
-* Solve an issue that could lead to severe memory issues and crashes when there are a lot of hoisted variables (#4183)
+* Solve severe memory issues and crashes with `var` declarations in deeply nested scopes (#4183) |
Rollup Version
v2.53.2
Operating System (or Browser)
macOS
Node Version (if applicable)
14.17.3
Link To Reproduction
N/A
Expected Behaviour
Memory usage remains similar between patch releases.
Actual Behaviour
For my project, v2.53.1 peaks at about 3.3 GB memory for the node process as reported by the macOS Activity Monitor. Rollup v2.53.2 peaks at about 4.8 GB.
The text was updated successfully, but these errors were encountered: