一文带你走进C++【内存泄漏】

背景

​没想到项目放到线上后,随着请求量的增多,却感觉到首屏速度越来越慢,并且是在持续性地变慢。而且在发布完后(也就是容器重建了),耗时又陡然降下来了。

​因此很合理地怀疑是内存泄漏了。故而在 STKE 的监控面板瞧一瞧,内存确实是一波一波似浪花。

1. 复现问题

知道是内存泄漏,我们就需要找到泄漏的点。因为不能轻易操作线上环境,线上代码也是压缩的,因此我们需要先搭建本地环境看能否方便调试问题。这里我们我们可以在本地起 Server 后,写脚本发起请求,来模拟线上环境。(但是看过上篇文章的小伙伴都知道,我们还有个骨架屏的模式,可以跳过发起 CGI 请求的步骤,大大降低单次请求耗时,让这个结果几秒钟就出来了)

我们可以使用 heapdump 包来将堆栈信息写入本地文件。heapdump 的基本使用姿势是这样的:

const heapdump = require('heapdump');
 
heapdump.writeSnapshot('./test.heapsnapshot');

然后就可以将堆栈文件导入到 Chrome 开发者工具的 Memory 栏来分析。这里我选择了分别是运行了 1 次、50 次、100 次 以及等待几秒钟垃圾回收后再写个 101 次的堆栈信息。可以看到堆栈文件越变越大,从 35M 增大到 249M。

选择两个堆栈文件做比较来分析,这里有个技巧就是按内存大小排序,然后看到同一个大小的对象个数非常多,那么很有可能就是它被引用了很多次,泄漏的点就可能在那里。然后就发现了问题可能出在 console 对象上。

2. 分析问题

正常地使用 console 对象不会造成内存泄漏,因此就怀疑是否是对 console 做了什么操作。搜索了一番代码,排除正常调用外,发现有个赋值的操作,就类似于下面这段代码:

const nativeError = console.error;
 
console.error = (...argv) => {
    // 省略一些操作
    nativeError(...argv);
};

这段代码在前端开发中其实是比较常见的,比如需要在 log 中自动添加时间:

const nativeError = console.error;
 
console.error = (...argv) => {
    nativeError(`[${(new Date()).toTimeString()}]`, ...argv);
};
 
console.error('Test');
// [20:58:17 GMT+0800 (中国标准时间)] Test

还有一个更常见的场景是,我们要在生产环境下屏蔽大部分的 log 输出,但是又要保留一个 log 函数引用,用来有时候在浏览器终端上输出一些关键信息,这时候会这么写:

// 引用,用来有时候在需要的时候上报
const logger = console.log;
 
// 必需用函数赋值,原有的一大堆使用 console.log('...') 的地方才不会报错
console.log = () => {};
 
logger('浏览器终端 AlloyTeam 招聘信息');

但是在我们的环境下,原来客户端的代码是被编译后放在 vm 里反复运行的,这会带来什么问题呢?

C/C++Linux服务器开发高级架构师/C++后台开发架构师​免费学习地址

【文章福利】另外还整理一些C++后台开发架构师 相关学习资料,面试题,教学视频,以及学习路线图,免费分享有需要的可以自行添加:Q群:720209036 点击加入~ 群文件共享

这里附个代码,感兴趣的小伙伴可以跑一下:

const vm = require('vm');
const heapdump = require('heapdump');
 
const total = 5000;
 
const writeSnapshot = (count) => {
    heapdump.writeSnapshot(`./${count}-${total}.heapsnapshot`);
};
 
const code = `
    const nativeError = console.error;
 
    console.error = (...argv) => {
        nativeError(argv);
    }
`;
 
const script = new vm.Script(cod
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值