大佬教程收集整理的这篇文章主要介绍了nodeJs内存泄漏问题详解,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
之前一次偶然机会发现,react 在server渲染时,当NODE_ENV != production时,会导致内存泄漏。具体issues: 。随着node,react同构等技术地广泛运用,node端内存泄漏等问题应该引起我们的重视。为什么node容易出现内存泄漏以及出现之后应该如何排查,下面通过一个简单的介绍以及例子来说明。
首先,node是基于v8引擎基础上,其内存管理方式与v8一致。下面简单介绍v8的相关内存特效。
node基于V8构建,通过V8的方式进行分配跟管理js对象。V8对内存的使用有限制(老生代内存64位系统下约为1.4G,32位系统下约为0.7G,新生代内存64位系统下约为32MB,32系统下约为16MB)。在这样的限制下,将导致无法操作大内存对象。如果不小心触碰这个界限,就会造成进程退出。
原因:V8在执行垃圾回收时会阻塞JavaScript应用逻辑,直到垃圾回收结束再重新执行JavaScript应用逻辑,这种行为被称为“全停顿”(stop-the-world)。若V8的堆内存为1.5GB,V8做一次小的垃圾回收需要50ms以上,做一次非增量式的垃圾回收甚至要1秒以上。
通过node --max-old-space-size=xxx(单位MB),node --max-new-space-size=xxx(单位KB) 设置新生代内存以及老生代内存来破解默认的内存限制。
V8的堆其实并不只是由老生代和新生代两部分构成,可以将堆分为几个不同的区域:
表示垃圾回收器在扫描内存空间时是否收集(增加)垃圾并在扫描周期结束时清空垃圾。
垃圾回收器只会针对新生代内存区、老生代指针区以及老生代数据区进行垃圾回收。对象首先进入占用空间较少的新生代内存。大部分对象会很快失效,非增量GC直接回收这些少量内存。假如有些对象一段时间内不能被回收,则进去老生代内存区。这个区域则执行不频繁的增量GC,且耗时较长。
Node的内存构成主要是通过V8进行分配的部分和Node自行分配的部分。受V8的垃圾回收限制的主要是V8的堆内存。造成内存泄漏的主要原因:1,缓存;2,队列消费不及时;3,作用域未释放
查看V8内存使用情况(单位bytE)
403_75@ @H_403_76@ress:进程的常驻内存部分
heap@R_355_10586@l,heapUsed:V8堆内存信息
查看系统内存使用情况(单位bytE)
os.@R_355_10586@lmem()
os.freemem()
返回系统总内存以及闲置内存
查看垃圾回收日志
node --trace_gc -e "var a = []; for( var i = 0; i < 1000000;="" i++="" )="" {="" a.push(new="" array(100));="" }"="">> gc.log //输出垃圾回收日志
node --prof //输出node执行时性能日志。 使用windows-tick.processor查看。
v8-profiler 对v8堆内存抓取快照和对cpu进行分析 node-heapdump 对v8堆内存抓取快照 node-mtrace 分析堆栈使用 node-memwatch 监听垃圾回收情况
403_75@ @H_403_76@
stats事件:每次进行全堆垃圾回收时,将触发一次stats事件。这个事件将会传递内存统计信息。
垃圾回收 "num_inc_gc": 8,//第几次增量垃圾回收 "heap_compactions": 8,//第几次对老生代进行整理 "estimated_base": 2592568,//预估基数 "currenT_Base": 2592568,//当前基数 "min": 2499912,//最小 "max": 2592568,//最大 "usage_trend": 0 //使用趋势 }观察num_full_gc和num_inc_gc反映垃圾回收情况。
leak事件:如果经过连续5次垃圾回收后,内存仍然没有被释放,意味着内存泄漏的发生。这个时候会触发一个leak事件。
403_75@ @H_403_76@Heap Diffing 堆内存比较 排查内存溢出代码。 下面,我们通过一个例子来演示如何排查定位内存泄漏:
var leakobjs = [];
function LeakClass(){
this.x = 1;
}
app.get('/',function(req,res){
console.log('get /');
for(var i = 0; i < 1000; i++){
leakobjs.push(new LeakClass());
}
res.send('
seTinterval(function(){
heapdump.writeSnapshot('./' + Date.Now() + '.heapsnapshot');
},3000);
http.listen(3000,function(){
console.log('listening on port 3000');
});
这里我们通过设置一个不断增加且不回被回收的数组,来模拟内存泄漏。
通过使用heap-dump模块来定时纪录内存快照,并通过chrome开发者工具profiles来导入快照,对比分析。
我们可以看到,在浏览器访问 localhost:3000 ,并多次刷新后,快照的大小一直在增长,且即使不请求,也没有减小,说明已经发生了泄漏。
接着我们通过过chrome开发者工具profiles,导入快照。通过设置comparison,对比初始快照,发送请求,平稳,再发送请求这3个阶段的内存快照。可以发现右侧new中LeakClass一直增加。在delta中始终为正数,说明并没有被回收。
针对内存泄漏可以采用植入memwatch,或者定时上报process.memoryUsage内存使用率到monitor,并设置告警阀值进行监控。
当发现内存泄漏问题时,若允许情况下,可以在本地运行node-heapdump,使用定时生成内存快照。并把快照通过chrome Profiles分析泄漏原因。若无法本地调试,在测试服务器上使用v8-profiler输出内存快照比较分析json(需要代码侵入)。
需要考虑在什么情况下开启memwatch/heapdump。考虑heapdump的频度以免耗尽了cpu。 也可以考虑其他的方式来检测内存的增长,比如直接监控process.memoryUsage()。
当心误判,短暂的内存使用峰值表现得很像是内存泄漏。如果你的app突然要占用大量的cpu和内存,处理时间可能会跨越数个垃圾回收周期,那样的话memwatch很有可能将之误判为内存泄漏。但是,这种情况下,一旦你的app使用完这些资源,内存消耗就会降回正常的水平。所以需要注意的是持续报告的内存泄漏,而可以忽略一两次突发的警报。
以上是大佬教程为你收集整理的nodeJs内存泄漏问题详解全部内容,希望文章能够帮你解决nodeJs内存泄漏问题详解所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。