Vue SSR 内存泄漏问题
yinxin630 opened this issue · comments
首先要明确的是, SSR 时只会执行同步的代码, 对于异步调用, 代码会执行但是不会等待完成. 对于 vue 组件, 仅执行到第一次 render 结束, 在 render 之前的阶段会执行到, 而之后的就不会. 之前的阶段包括 data 初始化、beforeCreate()、created()
在这些代码中, 务必小心不要造成内存泄漏
产生内容泄漏的常见情况
1. 使用全局变量
例如
function doSomething() {
a = 1;
}
doSomething();
a
被错误的定义为全局变量, 在 node 应用周期内将一直存在, 始终不会释放
可以用 eslint 避免这种错误定义全局变量的情况
2. setInterval / setTimeout
var a = 1;
setInterval(() => {
connsole.log(a);
}, 1000);
setTimeout(() => {
connsole.log(a);
}, 1000000) // 长时间不结束
如果 setInterval / setTimeout 内包含对上层作用域变量的引用, 那么该变量将无法释放
setInterval 定时器如果没有关闭逻辑的话, 将会一直触发. 并且每一次 SSR 过程都会新注册一个定时器
setTimeout 定时器虽然会在触发后退出, 接触对变量的引用, 但是通常不会立刻触发 GC, 该块内存仍会保留不定时间
因为 SSR 不等待异步结果, 所以最好在 SSR 时就别调用定时器
3. 闭包
闭包的情况会复杂一些, 并且通常难以定位
比如这个例子
var theThing = null;
var replaceThing = function () {
var originalThing = theThing;
var unused = function () {
if(originalThing) {}
};
theThing = {
longStr: Date.now() + Array(1000000).join('*'),
someMethod: function () {}
};
};
replaceThing();
replaceThing();
replaceThing();
... // call many times
思考下为什么会产生内存泄漏
在编写闭包时, 务必要注意变量的作用范围
4. 缓存
简单的使用 js 变量做缓存也可能造成内存泄漏
var cache = {}
function setCache(key, value) {
cache[key] = value;
}
要注意及时将不再需要的内容释放掉
如何排查内存泄漏
内存快照
- heapdump 记录内存快照
- Chrome Devtool Memory 分析内存快照
用法参考 https://www.bookstack.cn/read/node-in-debugging/2.2heapdump.md
实时内核性能监控分析工具
国人开发的 easy-monitor
用法参考 https://github.com/hyj1991/easy-monitor#ii-%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B