收集所有存在內(nèi)存泄漏的所有case熟菲。哪怕一個(gè)字節(jié)也不放過朴恳。
Case1:無限制增長的數(shù)組
varleakArray=[];exports.leak=function(){leakArray.push("leak"+Math.random());};
這個(gè)大概是最常見的內(nèi)存泄漏案例。只要變量leakArray不被回收呆贿,內(nèi)存就有可能無限上漲,且不被回收做入。
解決方案
確認(rèn)你push元素的數(shù)組對象是可以隨著作用域執(zhí)行結(jié)束回收竟块。
Case2:無限制設(shè)置屬性和值
這個(gè)情形在緩存對象中經(jīng)常出現(xiàn):
_.memoize=function(func,hasher){varmemo={};hasher||(hasher=_.identity);returnfunction(){varkey=hasher.apply(this,arguments);return_.has(memo,key)?memo[key]:(memo[key]=func.apply(this,arguments));};};
memoize方法主要是用來解決昂貴CPU耗用的js運(yùn)算的耐齐。它十分有用蒋情。但是在后端使用的時(shí)候要十分小心棵癣。因?yàn)閙emo對象是不會回收的夺衍,每次的參數(shù)不同都會在這個(gè)對象上添加屬性和值。
這個(gè)案例中沟沙,memo對象被當(dāng)作了緩存來使用,一直無法得到回收尝胆。
解決方案
關(guān)于如何規(guī)避這種無限制緩存的問題含衔,請移步到我另開的帖子中看解決方案:http://cnodejs.org/topic/4fafc843e7656c60680306f9
Case3:任何模塊內(nèi)的私有變量和方法均是永駐內(nèi)存的
(function(exports,require,module,__filename,__dirname){varcircle=require('./circle.js');console.log('The area of a circle of radius 4 is '+circle.area(4));exports.get=function(){returncircle();};});
任意編寫的模塊文件中,均會在頭和尾部上添加字符串贪染,以形成閉包杭隙,然后在require的過程中被調(diào)用一次因妙,并且將exports對象存儲在內(nèi)存中,直到進(jìn)程退出才會回收攀涵。
這個(gè)案例中以故,只是內(nèi)存不會回收,但一般不會造成內(nèi)存泄漏炉媒。需要注意的是私有變量不要通過exports上的方法為其添加內(nèi)存占用昆烁。
第一個(gè)案例其實(shí)就是由于這個(gè)原因造成的。
第四個(gè)案例來自于http://cnodejs.org/topic/4fcd020be5e72c25180032e5水援。
//OOM測試for(vari=0;i<100000000;i++){varuser={};user.name='outmem';user.pass='123456';user.email='outmem[@outmem](/user/outmem).com';}
這段代碼最主要的原因在于循環(huán)太大,直接內(nèi)存分配到超過v8內(nèi)存限制數(shù)量或渤。由于JavaScript事件循環(huán)的執(zhí)行機(jī)制奕扣,這段代碼沒有機(jī)會進(jìn)入下一個(gè)事件循環(huán)。用setInterval和setTimeout可以進(jìn)入下一個(gè)循環(huán)池磁。但是不推薦用setInterval和setTimeout楷兽。
在Node下有一個(gè)特殊的方法,process.nextTick();
for(vari=0;i<100000000;i++){process.nextTick(function(){varuser={};user.name='outmem';user.pass='123456';user.email='outmem[@outmem](/user/outmem).com';});}
不過這樣的效率可能不夠好筛圆。因?yàn)槊看味紱]有效利用好一次循環(huán)提岔。
一個(gè)建議是,一次事件循環(huán),不要超過10ms。太長時(shí)間的事件循環(huán)喷面,不僅會存在oom的風(fēng)險(xiǎn)磕瓷,還會阻塞后續(xù)IO的啟動(dòng)硕盹。
http://alinode.aliyun.com/blog/37