<html>

在极客教育出版了一个视频是关于《Node.js 内存泄漏分析》,本文章主要是从内容上介绍怎样来处理Node.js内存异常问题。假设希望学习可前往极客学院:http://www.jikexueyuan.com/course/2561.html
本文章的关键词
- 内存泄漏
- 内存泄漏检測
- GC分析
- memwatch


文章概要

由于内存泄漏在Node.js中非常的常见,可能在浏览器中应用javascript时。对于其内存泄漏不是特别敏感。但作为server语言执行时。你就不得不去考虑这些问题。由于非常小的逻辑可能导致server执行一天或者一个星期甚至一个月才会让你发现内存不断上涨。而终于会到那天你不得不重新启动服务来保护server的性能。那么这样的问题就有必要在上线前进行一个系统检測,同一时候在上线后能够有一个有效的监控程序来保证执行安全。

什么是内存泄漏

在介绍Node.js内存泄漏前。我们应该首先知道什么才是内存泄漏。内存泄漏又包括哪些类型。

内存泄漏概念

内存泄漏也称作“存储渗漏”。用动态存储分配函数,动态开辟的空间,在使用完毕后未释放,结果导致一直占领该内存单元,直到程序结束。
上面的定义来自百度百科,当然从上面的定义我们就能够了解到内存泄漏简单说。就是占用着系统资源而一直不释放,所导致的系统资源越来越少,从而导致系统异常的一个比較严重的问题,能够使用以下来解释内存泄漏。


Node.js服务程序假定是一次“班级大扫除”。系统内存资源假定为班级的资源“五个扫把”。而利用资源进行工作的“学生”,这里我们假定为进程。

当天学校要进行大扫除,每一个班级仅仅有五把扫把。每一个人都须要完毕一部分扫地工作,学生完毕后自己主动给其它人。当全部人完毕扫地工作,大扫除结束,老师首次会将扫把分配给五个人,可是这五个人中存在几个同学手握扫把不做事,即使做完事了,也不会将扫把分配给其它人。导致其它人的扫地工作一直无法进行下去,或者由于扫把有限导致打扫工作进行的非常漫长。

内存泄漏类型

内存泄漏包括的类型有:常发性、偶发性、一次性、隐式。

  • 常发性
    发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。

  • 偶发性
    发生内存泄漏的代码仅仅有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的或许就变成了常发性的。

  • 一次性
    发生内存泄漏的代码仅仅会被执行一次,或者由于算法上的缺陷,导致总会有一块且仅一块内存发生泄漏。比方,在类的构造函数中分配内存。在析构函数中却没有释放该内存,所以内存泄漏仅仅会发生一次。

  • 隐式
    其主要是在调用函数或者模块时,当參数或者输入没有达到界定值时,是不会发生泄漏,当參数或者输入值达到一定时,才会发现内存泄漏,我们称这样的为隐式。程序在执行过程中不停的分配内存,可是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,由于终于程序释放了全部申请的内存。可是对于一个server程序。须要执行几天、几周甚至几个月,不及时释放内存也可能导致终于耗尽系统的全部内存。

    所以。我们称这类内存泄漏为隐式内存泄漏。

    隐式才是我们本文中所须要去探索,去发现和解决的异常问题。

Node.js内存泄漏会带来的危害

Node.js内存泄漏究竟会有哪些危害,既然我们希望去发现和检測内存泄漏,那么我们就必须要首先知道Node.js内存泄漏究竟会影响哪些问题。

用户服务异常

普通情况下用户是无法察觉内存泄漏带来的影响,可是对于有些情况下,由于内存泄漏可能导致用户响应非常慢,这样的情况下对于用户而言无法感受到异常,可是能够普遍感受到服务响应变慢。而且这样的情况可能会导致新注冊用户丢失等问题。

server性能异常

普通情况下。内存泄漏直接的影响就是server,server会由于内存的不断上涨,从而系统资源可使用的空间越来越小,这样就会慢慢的导致该服务影响到server中其它的一些基础服务的执行,从而导致server越来越慢,同一时候导致可使用资源越来越少,直接导致server资源耗尽,server异常,导致数据丢失等等,比較严重的问题。

常见的 Node.js 内存泄漏问题

这里主要介绍两种关于内存泄漏的代码逻辑,主要是循环引用和无克制循环带来的内存泄漏。

循环引用

这部分在javascript中可能更比較常见。其主要介绍的是说:A对象包括一个指向B的指针。对象B也包括一个指向A的引用。 这就可能造成大量内存得不到回收(内存泄露)。由于它们的引用次数永远不可能是 0 。因此作为回收机制是不会将A和B进行回收的。

var func = function () {}
var el = function () {}
el.func = func;
func.element = el;

比如上面代码中el和func互相引用。而且这样的类型的内存泄漏能够说是常发性。

无克制循环

没有对数组有不论什么限制,而且在数组过大时,没有进行有效的回收处理机制。

模块中的私有方法和属性
随意编写的模块文件里,均会在头和尾部上加入字符串。以形成闭包,然后在require的过程中被调用一次,而且将exports对象存储在内存中。直到进程退出才会回收。

这样的严格上说并不是内存泄漏,仅仅是说须要严格注意模块中的私有变量和方法的使用,避免由于过多的私有变量占用到了过多的系统内存。


假定我们有模块leak.js

var leakArray = [];   
exports.leak = function () {  
  leakArray.push("leak" + Math.random());  
};

那么假设我们创建一个test.js来引用该模块,执行时。则会看的leakArray一直变大。

var Mod = require('./leak');
Mod.leak();
Mod.leak();
Mod.leak();
Mod.leak();
Mod.leak();

假设这里我们无克制的调用方法leak时,就可能导致数组过大,从而导致一定的问题。

过大的数组循环
先看下例如以下代码:

for ( var i = 0; i < 100000000; i++ ) {
    var user       = {};
    user.name  = 'outmem';
    user.pass  = '123456';
    user.email = 'outmem[@outmem](/user/outmem).com';
}

这段代码最基本的原因在于循环太大,直接内存分配到超过v8内存限制数量。

由于JavaScript事件循环的执行机制,这段代码没有机会进入下一个事件循环。

用setInterval和setTimeout能够进入下一个循环。

可是不推荐用setInterval和setTimeout。对于大循环代码,建议最好是切割。然后进行处理,分段进行处理。由于每次都没有效利用好一次循环。

一次事件循环。不要超过10ms。

Node.js内存泄漏工具使用实践

这里主要介绍一些常见的Node.js内存泄漏检測工具,而且针对当中的memwatch以及heapdump来进行详细的实践学习。

Node.js内存泄漏工具

node-inspector提供了绑定在Node中的V8分析器和一个基于WebKit Web Inspector的debug界面,大家能够看下这篇博文,当中就是介绍怎样应用该工具来检測内存泄漏
http://www.cnblogs.com/ldlchina/p/4762036.html

node-mtrace,它使用了GCC的mtrace工具来分析堆的使用。
https://github.com/Jimbly/node-mtrace
可是该工具提供的是点对点的,假设存在异步函数的话。会比較麻烦。这样的能够结合其它工具一起使用会比較方便,大家能够看下github的演示样例代码

node-heap-dump对V8的堆抓取了一张快照并把全部的东西序列化进一个巨大的JSON文件。它还包括了一些分析研究快照结果的JavaScript工具。这里在memwatch中我们是会应用该工具对应的功能来定位泄漏代码逻辑。

memwatch
是一个专门用来检測和监控内存泄漏的工具,其不仅仅能够在上线前进行扫描监控。也能够在上线后进行有效的内存泄漏检測。


接下来的话,我们就实践应用memwatch来检測内存泄漏的以及通过heapdump抓取GC,进行GC内存分析实践。

memwatch的实践

在学习memwatch之前。首先须要安装配置对应的模块,详细操作能够使用npm install memwatch。下载该模块的时候须要进行编译,因此须要python2.6以上以及须要VS2012以上。

假设以上配置遇到问题的时候。能够在我的资料中寻找一篇关于怎样解决这两个问题的博文链接http://blog.csdn.net/dan_blog/article/details/50707278
那么接下来我们就来实践应用该模块,首先我们看一下简单的实例代码:

var http = require('http');
var server = http.createServer(function (req, res) {
    for (var i=0; i<1000; i++) {
        server.on('request', function leakyfunc() {});
    }
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');

从代码本身看其是存在一定的问题,随着用户每一次请求,其内存占用都会提供,我们停止请求一段时间时,其内存也不会减少,说明该段代码存在一定的问题。


大家能够前往极客学院视频地址中下载该代码的源代码,当中还包括了其它资料
能够执行下该段代码,假设使用http://127.0.0.1:1337不断的进行訪问,假设在windows下能够在进程中查看该进程内存的使用情况
这里写图片描写叙述
假设你是在Linux的话。能够首先通过命令查看该进程ID,然后再使用top -p 进程ID

ps -ef | grep node
top -p 12202

随时的查看进程所占用的内存。通过訪问你会看到其内存的变化情况,同一时候发现其内存并不会慢慢释放回来。
既然出现了上面的内存泄漏,那么我们就使用memwatch以及heapdump来做检測和分析,改进后的代码例如以下。

var http = require('http');
var memwatch = require('memwatch');
var hd       = new memwatch.HeapDiff();
var heapdump = require('heapdump');
var server = http.createServer(function (req, res) {
    for (var i=0; i<1000; i++) {
        server.on('request', function leakyfunc() {});
    }
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
memwatch.on('leak', function(info) {
    var diff = hd.end();
    console.log(JSON.stringify(diff));

    var file = '/tmp/myapp-' + process.pid + '-' + Date.now() + '.heapsnapshot';
    heapdump.writeSnapshot(file, function(err){
        if (err) console.error(err);
        else console.error('Wrote snapshot: ' + file);
    });
});
server.setMaxListeners(0);
console.log('Server running at http://127.0.0.1:1337/. Process PID: ', process.pid);

上面的逻辑中包括了使用memwatch来检測内存泄漏,同一时候还包括了使用heapdump来抓取内存的实时情况,通过执行如上代码,然后使用压測工具对http://127.0.0.1:1337进行压測,当压測到一定的情况后。在执行窗体你能够看的其内存泄漏的提醒。并在这时候会在file这个文件夹文件里(假设在windows中最好就改动下file这个文件路径,这里的演示样例代码是相对Linux环境的)记下当前内存泄漏时的内存GC情况。

GC内存分析

既然获取到该文件后,我们再使用google chrome的工具来分析GC的内存情况,并查看出导致内存泄漏的原因。
这里写图片描写叙述
打开工具后,再使用Load,将我们刚生成的文件载入进去。
载入进去以后关于分析方法,大家能够參考该文章
http://itindex.net/detail/52929-chrome-%E5%BC%80%E5%8F%91-%E5%B7%A5%E5%85%B7
里面有详情的介绍。当然假设想了解更详细的分析方法。大家能够去极客学院上查看本课程的视频学习资料。

总结

这就是本文所介绍的知识。在看完本文以后。大家至少了解什么是内存泄漏。Node.js的内存泄漏会导致哪些问题,以及怎样应用memwatch和heapdump来检測和分析内存泄漏问题。同一时候须要简单了解Chrome中的内存分析工具的使用。

版权声明:本文为博主原创文章。未经博主同意不得转载。

举报

  • 本文已收录于下面专栏:

相关文章推荐

安装bcrypt报错node-gyp rebuild解决方法

npm install bcrypt –save引起了让人非常烦恼的错误,整个人心情都不好了。下边是个人的解决方法:错误一缺少python环境:G:\nodejs\moviesite\node_modu...

怎样自己检查NodeJS的代码是否存在内存泄漏

追踪NodeJS代码中的内存泄漏一直是一个非常有挑战的难题。本文讨论怎样从一个node写的应用里自己主动的跟踪到内存泄漏问题,在这里笔者向大家推荐两款追查内存问题的神器 —— memwatch 和 heap...

Node.js的内存管理

本文为读书笔记。 一、V8的垃圾回收机制与内存限制 Node使用chrome的V8作为JS脚本引擎,因此Node的内存管理与V8关系非常密切。 1.V8的内存限制 由于V8是为浏览器环境设...

Node——内存控制

JS在浏览器中执行的时候并不存在太大的内存问题。我们通常也不刻意的去优化他们。可是当执行在server端的时候,执行时间长,这样的问题就不得不考虑了。 V8的垃圾回收机制与内存限制 V8的内存限制 ...

Node.js学习1_记一次 Node.js 应用内存暴涨分析

起因 之前 TMS 在执行时 CPU 中占用率和内存占用一直非常高。导致应用执行状态不是非常良好,须要频繁重新启动。经过排查。找出了部分原因: 使用的 html-minifier 模块有问题,假设输...

深入浅出NodeJS——内存控制

V8虚拟机的内存回收机制。和Java虚拟机相似採用分代回收机制。分为新生代和老生代,当满足一定条件新生代对象会晋级到老生代。

利用Node在服务端编程要小心内存泄露问题,一个小的泄露因为大量并发訪问可能...

深入浅出nodejs学习笔记--第五章 内存控制

深入浅出nodejs学习笔记 -- 第五章 内存控制 简介了js的垃圾回收和内存监管机制和V8的内存控制机制以及常见的内存限制算法

Linux内存描写叙述之内存节点node--Linux内存管理(二)

日期 内核版本号 架构 作者 GitHub CSDN 2016-08-31 Linux-4.7 X86 & arm gatieme LinuxDeviceDrive...

Node.js 调试 GC 以及内存暴涨的分析

https://blog.eood.cn/node-js_gc 近期做的server端组件大部分都在使用 Node.js 。

由于 Node.js 库管理模式比較先进。而且依托于 Github 的流行。...

node.js内存泄漏分析二

概述在开发过程中,遇到了部分导致内存泄露的情况,本文主要是说明几种内存泄漏的问题,并简单分析一些关于内測泄漏分析的方法。

内存泄漏分析1. 使用heapdump模块模块介绍:https://github...

  • 微博
    微信
    QQ
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多仅仅同意输入30个字)

posted @ 2017-08-14 16:27  claireyuancy  阅读(189)  评论(0编辑  收藏  举报