-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Memory leak #11901
Comments
Solution: After I removed {deep: true} in all "watch" functions the problem disappeared. |
Could you please check the reproduction link? It seems to be inaccessible. |
I can't provide full repro code because I have a complex commercial project from which it is difficult to extract repro code. The fact is that "watch" with {deep: true} starts to leak. |
We can't analyze the bug without a runnable minimal reproduction. |
I don't know if this mini demo is what you wanted to see, but even from it you can see that when comparing memory snapshots, the Dep class is not cleared by GC. |
I'm not sure if it is related but when debugging a reactivity issue in one of my
I wonder if a memory leak could be caused by the redundant Unfortunately I'm still struggling to isolate the issue. :-/ PS. The issue I'm debugging is about a |
I also deliberately launched the demo in incognito mode. As you can see from the screenshot, the memory is gradually growing from snapshot to snapshot. Deps is also growing and is not cleared. Even deliberately calling the garbage collector from devtools does not improve the situation. |
Thank you very much for this patch, it explains why all my applications made with the Quasar framework lagged, and the browser froze. |
Hello, Important note: this happens in dev mode, in release mode everything's fine (for now), I'm using the Quasar framework and Vite/yarn for the build. |
@rxdiscovery |
Might be related to c74bb8c @rxdiscovery can you try the commit release here (set vue dependency in package.json to |
Hello, @yyx990803 I'll test the c74bb8c version and give you feedback as soon as possible. I'm currently investigating the cause, there are 3 potential causes :
@edison1105 @yyx990803 (in the video, the first minute the application is reactive, but in minute 4 and +, it lags until it freezes.) |
@rxdiscovery |
Hello, to avoid any pollution, I created a new virtual machine with debian and the latest version of nodeJS and the latest version of Firefox. then I tested your suggestions:
"dependecies" : {
...
"vue" : "https://pkg.pr.new/vue@cbc39d5"
...
}
"dependecies" : {
...
"vue" : "https://pkg.pr.new/vue@11971"
...
}
even if I force my Vue version, does quasar still use 3.5.5 internally? Is the problem related to this issue? Or are we on the wrong track and I have to open another issue? |
@rxdiscovery |
@edison1105 There is a leak in Vue, it is located at the level of :
Chrome memory profiling : Firefox memory profiling : it's like there's a loop ! perhaps the problem lies here: const patchKeyedChildren = (c1, c2, container, parentAnchor, parentComponent, parentSuspense, namespace, slotScopeIds, optimized) => {
let i = 0;
const l2 = c2.length;
let e1 = c1.length - 1;
let e2 = l2 - 1;
while (i <= e1 && i <= e2) {
const n1 = c1[i];
const n2 = c2[i] = optimized ? cloneIfMounted(c2[i]) : normalizeVNode(c2[i]);
if (isSameVNodeType(n1, n2)) {
patch(
n1,
n2,
container,
null,
parentComponent,
parentSuspense,
namespace,
slotScopeIds,
optimized
);
} else {
break;
}
i++;
}
while (i <= e1 && i <= e2) {
const n1 = c1[e1];
const n2 = c2[e2] = optimized ? cloneIfMounted(c2[e2]) : normalizeVNode(c2[e2]);
if (isSameVNodeType(n1, n2)) {
patch(
n1,
n2,
container,
null,
parentComponent,
parentSuspense,
namespace,
slotScopeIds,
optimized
);
} else {
break;
}
e1--;
e2--;
}
if (i > e1) {
if (i <= e2) {
const nextPos = e2 + 1;
const anchor = nextPos < l2 ? c2[nextPos].el : parentAnchor;
while (i <= e2) {
patch(
null,
c2[i] = optimized ? cloneIfMounted(c2[i]) : normalizeVNode(c2[i]),
container,
anchor,
parentComponent,
parentSuspense,
namespace,
slotScopeIds,
optimized
);
i++;
}
}
} else if (i > e2) {
while (i <= e1) {
unmount(c1[i], parentComponent, parentSuspense, true);
i++;
}
} else {
const s1 = i;
const s2 = i;
const keyToNewIndexMap = /* @__PURE__ */ new Map();
for (i = s2; i <= e2; i++) {
const nextChild = c2[i] = optimized ? cloneIfMounted(c2[i]) : normalizeVNode(c2[i]);
if (nextChild.key != null) {
if (keyToNewIndexMap.has(nextChild.key)) {
warn$1(
`Duplicate keys found during update:`,
JSON.stringify(nextChild.key),
`Make sure keys are unique.`
);
}
keyToNewIndexMap.set(nextChild.key, i);
}
}
let j;
let patched = 0;
const toBePatched = e2 - s2 + 1;
let moved = false;
let maxNewIndexSoFar = 0;
const newIndexToOldIndexMap = new Array(toBePatched);
for (i = 0; i < toBePatched; i++)
newIndexToOldIndexMap[i] = 0;
for (i = s1; i <= e1; i++) {
const prevChild = c1[i];
if (patched >= toBePatched) {
unmount(prevChild, parentComponent, parentSuspense, true);
continue;
}
let newIndex;
if (prevChild.key != null) {
newIndex = keyToNewIndexMap.get(prevChild.key);
} else {
for (j = s2; j <= e2; j++) {
if (newIndexToOldIndexMap[j - s2] === 0 && isSameVNodeType(prevChild, c2[j])) {
newIndex = j;
break;
}
}
}
if (newIndex === void 0) {
unmount(prevChild, parentComponent, parentSuspense, true);
} else {
newIndexToOldIndexMap[newIndex - s2] = i + 1;
if (newIndex >= maxNewIndexSoFar) {
maxNewIndexSoFar = newIndex;
} else {
moved = true;
}
patch(
prevChild,
c2[newIndex],
container,
null,
parentComponent,
parentSuspense,
namespace,
slotScopeIds,
optimized
);
patched++;
}
}
const increasingNewIndexSequence = moved ? getSequence(newIndexToOldIndexMap) : EMPTY_ARR;
j = increasingNewIndexSequence.length - 1;
for (i = toBePatched - 1; i >= 0; i--) {
const nextIndex = s2 + i;
const nextChild = c2[nextIndex];
const anchor = nextIndex + 1 < l2 ? c2[nextIndex + 1].el : parentAnchor;
if (newIndexToOldIndexMap[i] === 0) {
patch(
null,
nextChild,
container,
anchor,
parentComponent,
parentSuspense,
namespace,
slotScopeIds,
optimized
);
} else if (moved) {
if (j < 0 || i !== increasingNewIndexSequence[j]) {
move(nextChild, container, anchor, 2);
} else {
j--;
}
}
}
}
}; |
the only thing we need is a minimal reproduction not screenshots |
@edison1105 I'm currently analyzing the source code of Quasar's “QSelect”, to reproduce something similar in Vue, then I'll be able to give you a code without any dependencies. |
@rxdiscovery try v3.5.7 by the way. We fixed some memory leaks yesterday. |
I've already done the test, but unfortunately the problem persists. |
Vue version
3.5.4
Link to minimal reproduction
http://cant.insert.code/commercial_project
Steps to reproduce
The problem started to appear in Vue 3.5.* (including version 3.5.4). There are no problems in version 3.4.38.
In my case, the approximate source of the problem is an active websocket connection.
What is expected?
No memory leak
What is actually happening?
After establishing a socket connection from which data is coming, the memory grows infinitely. Moreover, the more socket connections, the more the memory grows without stopping. With 10 connections in 5-10 minutes, the heap size consumption is more than 3 GB.
An example of how a leak starts after the application starts:
At the same time, taking memory snapshots is very difficult because the snapshot formation often gets stuck at the stage (Building dominator tree).
If you still manage to take a memory snapshot, it turns out that the preliminary cause is deps (I may be wrong).
I want to clarify that in case of a leak:
DOM Nodes - do not change.
JS Event Listeners - do not change.
System Info
Any additional comments?
No response
The text was updated successfully, but these errors were encountered: