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
[Bug] Memory leak when switch page & all sort of things #78
Comments
我也觉得有内存泄漏,但是就是找不到究竟漏在哪了。现在用的组件库很有可能会漏内存,但是真的不好调试 ... |
Electrion或者Javascript,没有类似于C++什么的内存泄漏的检测工具之类的嘛 |
Chrome 开发者工具就有 Memory Profiler ,但我不太会用 ... 在频繁切换页面的时候,比如在首页,点击推荐歌单进入歌单详情页面,等待加载完成后返回,重复多次,内存的增长速度会非常快,而且几乎不会下降。刚刚启动应用时,JavaScript heap 的用量大概是 12M ,打开歌单详情页面约 10 次后,就会增长到 60-80M ,而且放置很长时间后都不会下降。同时 Performance 中的 Nodes 和 Listeners 数量会由几百增长至几千甚至数万,而且并没有下降的趋势。 目前发现了一点: electron-netease-cloud-music/src/renderer/App.vue Lines 5 to 9 in 86a895f
这个 transition/keep-alive/router-view 的组合,会导致经过 router-view 的 DOM 元素无法被销毁。如果把 keep-alive 换成 div ,内存泄漏问题几乎立即消失,无论怎么切换页面, JavaScript heap 的用量都会维持在 16M 左右,过一段时间后慢慢降到 12M,而且 Nodes 和 Listeners 数量也会保持在 1000 以下,但页面间切换时的动画就没有了。 不知道到底是我写错了,还是这一套东西有 bug ,有待更仔细的研究 ... |
这是开发者工具中 Memory 面板中一个 Heap snapshot 的部分结构,注意这张图的层级是反着的,最下面的是根元素,往上是它的属性。 更具体的细节:router-view 中的一个组件被 keep-alive 的 include 所包含,它被加到了 keep-alive 的 cache 中。在 router-view 切换到另外的路由时,被 cache 住的组件通过 parent.parent.children.children 间接引用到了另外路由的组件,而这个被引用的组件的 VNode 又引用了它自己的 DOM 子树,这导致所有经过 router-view 的组件的 DOM 子树均被第一个 keep-live 的组件所引用,都无法被回收。 |
确认是 keep-alive 的 bug ,详情见 vuejs/vue#9842 vuejs/vue-router#2549 ,已有 PR vuejs/vue#9875 vuejs/vue#9962 但是还没合并,目前的 workaround 应该是从 PR 里面复制一个 keep-alive 过来用吧 ... |
should be fixed by f12a5eb |
还有很多地方在泄漏,而且涉及到 Vue 以及 Chromium 的 bug ,详见 vuejs/vue#10004 中的讨论。 vuejs/vue#10085 虽然修复了 VueComponent 的泄漏,但是 DOM Elements 仍然在泄漏,目前找不到好的解决方案。 |
在 Vue 的 Pull Request 里面翻了一下,找到了一些可以修复内存泄漏问题的 patch ,经过测试,虽然每次切换页面或者按播放/暂停按钮还是会泄漏几个 VueComponent ,但是很大的内存泄漏应该不会有了 ... 使用 patch-package 在 CI 打包之前应用 patch ,不出意外的话在 v0.9.18 应该就能生效。 使用的 patch 列表: f820d77 目前 patch 了 vue 以及 vue-resize ,而且 vue-resize 的 patch 内容已经被合并了, Akryum/vue-resize#62 |
终于又发现了一处内存泄漏,只要音乐在播放,下方的进度条组件在更新,就会一直漏 VueComponent ,研究了一会发现是这个东西泄漏了: 还是个 functional component ,都不知道说什么好了 ... 改成一般的组件之后,就不漏了: 马上发新版本,这下总该没问题了吧 ... |
这个不提交PR?还是说这个是临时处理,然后等官方修复再改过来?
我马上开始测试,我明天反馈看看结果怎么样 |
Muse UI 已经一年多没人维护了,提交了 PR 也不会被合并了,只能自己 fork 一下用用,这样子 … |
其实我觉得不是很正常,如果只是听音乐,别的什么都不做的话,不应该有特别明显的占用上升。 在不泄漏的情况下,会额外占用内存的只有播放列表和私人 FM 的存储,以及 keep-alive 的首页/歌词页/我的收藏页面。打开控制台看一下,是不是还开着 debug log ,有没有很多输出,如果有的话,执行一下 localStorage.removeItem('debug') 把它关掉 |
目前只能说是减缓内存泄漏的速度了,虽然 VueComponent 不泄漏了,又发现了 VNode 泄漏的情况 ... 和之前 #78 (comment) 的情况差不多,也是 parent children 的循环引用 ... Vue 现在的工作重心都在 Vue 3 ,短时间内没人会管了,看我有没有机会读一读 Vue 的源码自己修一下了 ... |
这个有什么更新么?经常性的需要杀掉进程降低内存消耗有点麻烦 |
终于!发现了 VNode 泄漏的原因,也找到了解决方法,这次 Muse UI 要背锅 https://github.com/rocka/muse-ui/blob/v3.0.7/src/internal/directives/click-outside.js#L7-L9 在 directive 的 bind 方法中,声明的 既然这个 directive 的目的是在 var clickOutSide = {
name: 'click-outside',
bind (el, binding) {
const documentHandler = function (e) {
if (el.contains(e.target)) return;
el[clickoutsideContext].bindingFn(e);
};
el[clickoutsideContext] = {
documentHandler,
bindingFn: binding.value
};
setTimeout(() => {
document.addEventListener('click', documentHandler);
}, 0);
},
update (el, binding) {
el[clickoutsideContext].bindingFn = binding.value;
},
unbind (el) {
document.removeEventListener('click', el[clickoutsideContext].documentHandler);
delete el[clickoutsideContext];
}
}; 这样改完以后,内存占用终于平稳了: |
🤣 我靠,太强了吧。这个啥时候可以更新啊,我好赶紧去下载新版本 |
刚发了新版本,应该可以下载了 |
GPU 进程是没法控制的,归 chromium 管, electron 能控制的就只有主进程( |
明白。现在已经用了几天没退出,Renderer的内存开销还是维持在110MB左右,我觉得这个算是解决了。👍 |
大佬好强 👍 |
当前版本:
v0.9.6-1
描述:
目前已经好几天没有关机了,然后我发现NCM的renderer的内存奇高,有4.15G(昨晚上是4G,白天打开后就变成了4.15G)
如果重启,默认启动的内存占用只有67MB
The text was updated successfully, but these errors were encountered: