yinxin630 / blog

Personal technology blog

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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;
}

要注意及时将不再需要的内容释放掉

如何排查内存泄漏

内存快照

  1. heapdump 记录内存快照
  2. 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