您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“nodejs如何檢查內(nèi)存泄漏”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
node中可利用memwatch工具來(lái)檢查內(nèi)存泄漏,方法:1、使用npm進(jìn)行工具的安裝;2、在項(xiàng)目中添加“var memwatch=require('memwatch');memwatch.setup();”代碼;3、監(jiān)聽(tīng)leak事件即可。
本教程操作環(huán)境:windows7系統(tǒng)、nodejs 12.19.0版,DELL G3電腦。
追蹤Node.js代碼中的內(nèi)存泄漏一直是一個(gè)很有挑戰(zhàn)的難題。本文討論如何從一個(gè)node寫(xiě)的應(yīng)用里自動(dòng)的跟蹤到內(nèi)存泄漏問(wèn)題,在這里筆者向大家推薦兩款追查內(nèi)存問(wèn)題的神器 —— memwatch 和 heapdump
首先,我們來(lái)看一個(gè)簡(jiǎn)單的內(nèi)存泄漏
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'); server.setMaxListeners(0); console.log('Server running at http://127.0.0.1:1337/. Process PID: ', process.pid);
每一個(gè)請(qǐng)求我們?cè)黾恿?000個(gè)導(dǎo)致泄漏的監(jiān)聽(tīng)器。如果我們?cè)谝粋€(gè)shell控制臺(tái)中執(zhí)行以下命令:
while true; do curl http://127.0.0.1:1337/; done
然后在另外一個(gè)shell控制臺(tái)中查看我們的進(jìn)程
top -pid
我們會(huì)看到node進(jìn)程產(chǎn)生異常高的內(nèi)存占用,我們的node進(jìn)程看起來(lái)失控了。那么,當(dāng)我們的node進(jìn)程出現(xiàn)這種情況的時(shí)候,通常我們?cè)撛鯓釉\斷出問(wèn)題的根源?
npm模塊 memwatch 是一個(gè)非常好的內(nèi)存泄漏檢查工具,讓我們先將這個(gè)模塊安裝到我們的app中去,執(zhí)行以下命令:
npm install --save memwatch
然后,在我們的代碼中,添加:
var memwatch = require('memwatch'); memwatch.setup();
然后監(jiān)聽(tīng) leak 事件
memwatch.on('leak', function(info) { console.error('Memory leak detected: ', info); });;
這樣當(dāng)我們執(zhí)行我們的測(cè)試代碼,我們會(huì)看到下面的信息:
{ start: Fri Jan 02 2015 10:38:49 GMT+0000 (GMT), end: Fri Jan 02 2015 10:38:50 GMT+0000 (GMT), growth: 7620560, reason: 'heap growth over 5 consecutive GCs (1s) - -2147483648 bytes/hr' }
memwatch發(fā)現(xiàn)了內(nèi)存泄漏!memwatch 判定內(nèi)存泄漏事件發(fā)生的規(guī)則如下:
當(dāng)你的堆內(nèi)存在5個(gè)連續(xù)的垃圾回收周期內(nèi)保持持續(xù)增長(zhǎng),那么一個(gè)內(nèi)存泄漏事件被派發(fā)
了解更加詳細(xì)的內(nèi)容,查看 memwatch
使用memwatch我們發(fā)現(xiàn)了存在內(nèi)存泄漏,這非常好,但是現(xiàn)在呢?我們還需要定位內(nèi)存泄漏出現(xiàn)的實(shí)際位置。要做到這一點(diǎn),有兩種方法可以使用。
通過(guò)memwatch你可以得到堆內(nèi)存使用量和內(nèi)存隨程序運(yùn)行產(chǎn)生的差異。詳細(xì)的文檔在這里
例如,我們可以在兩個(gè)leak事件發(fā)生的間隔中做一個(gè)heap dump
:
var hd; memwatch.on('leak', function(info) { console.error(info); if (!hd) { hd = new memwatch.HeapDiff(); } else { var diff = hd.end(); console.error(util.inspect(diff, true, null)); hd = null; } });
執(zhí)行這段代碼會(huì)輸出更多的信息:
{ before: { nodes: 244023, time: Fri Jan 02 2015 12:13:11 GMT+0000 (GMT), size_bytes: 22095800, size: '21.07 mb' }, after: { nodes: 280028, time: Fri Jan 02 2015 12:13:13 GMT+0000 (GMT), size_bytes: 24689216, size: '23.55 mb' }, change: { size_bytes: 2593416, size: '2.47 mb', freed_nodes: 388, allocated_nodes: 36393, details: [ { size_bytes: 0, '+': 0, what: '(Relocatable)', '-': 1, size: '0 bytes' }, { size_bytes: 0, '+': 1, what: 'Arguments', '-': 1, size: '0 bytes' }, { size_bytes: 2856, '+': 223, what: 'Array', '-': 201, size: '2.79 kb' }, { size_bytes: 2590272, '+': 35987, what: 'Closure', '-': 11, size: '2.47 mb' }, ...
所以在內(nèi)存泄漏事件之間,我們發(fā)現(xiàn)堆內(nèi)存增長(zhǎng)了2.47MB,而導(dǎo)致內(nèi)存增長(zhǎng)的罪魁禍?zhǔn)资?strong>閉包。如果你的泄漏是由某個(gè)class造成的,那么what
字段可能會(huì)輸出具體的class名字,所以這樣的話(huà),你會(huì)獲得足夠的信息來(lái)幫助你最終定位到泄漏之處。
然而,在我們的例子中,我們唯一獲得的信息只是泄漏來(lái)自于閉包,這個(gè)信息非常有用,但是仍不足以在一個(gè)復(fù)雜的應(yīng)用中迅速找到問(wèn)題的來(lái)源(復(fù)雜的應(yīng)用往往有很多的閉包,不知道哪一個(gè)造成了內(nèi)存泄漏——譯者注)
所以我們?cè)撛趺崔k呢?這時(shí)候該Heapdump出場(chǎng)了。
npm模塊node-heapdump是一個(gè)非凡的模塊,它可以使用來(lái)將v8引擎的堆內(nèi)存內(nèi)容dump出來(lái),這樣你就可以在Chrome的開(kāi)發(fā)者工具中查看問(wèn)題。你可以在開(kāi)發(fā)工具中對(duì)比不同運(yùn)行階段的堆內(nèi)存快照,這樣可以幫助你定位到內(nèi)存泄漏的位置。要想了解heapdump的更多內(nèi)容,可以閱讀這篇文章
現(xiàn)在讓我們來(lái)試試 heapdump,在每一次發(fā)現(xiàn)內(nèi)存泄漏的時(shí)候,我們都將此時(shí)的內(nèi)存堆??煺諏?xiě)入磁盤(pán)中:
memwatch.on('leak', function(info) { console.error(info); 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); }); });
運(yùn)行我們的代碼,磁盤(pán)上會(huì)產(chǎn)生一些.heapsnapshot
的文件到/tmp
目錄下?,F(xiàn)在,在Chrome瀏覽器中,啟動(dòng)開(kāi)發(fā)者工具(在mac下的快捷鍵是alt+cmd+i),點(diǎn)擊Profiles
標(biāo)簽并點(diǎn)擊Load
按鈕載入我們的快照。
我們能夠很清晰地發(fā)現(xiàn)原來(lái)leakyfunc()是內(nèi)存泄漏的元兇。
我們依然還可以通過(guò)對(duì)比兩次記錄中heapdump的不同來(lái)更加迅速確認(rèn)兩次dump之間的內(nèi)存泄漏:
想要進(jìn)一步了解開(kāi)發(fā)者工具的memory profiling
功能,可以閱讀 Taming The Unicorn: Easing JavaScript Memory Profiling In Chrome DevTools 這篇文章。
我們給Turbo - FeedHenry開(kāi)發(fā)的測(cè)試工具提交了一個(gè)小補(bǔ)丁 — 使用了上面所說(shuō)的內(nèi)存泄漏檢查技術(shù)。這樣就可以讓開(kāi)發(fā)者寫(xiě)針對(duì)內(nèi)存的單元測(cè)試了,如果模塊有內(nèi)存問(wèn)題,那么測(cè)試結(jié)果中就會(huì)產(chǎn)生相應(yīng)的警告。詳細(xì)了解具體的內(nèi)容,可以訪問(wèn)Turbo模塊。
“nodejs如何檢查內(nèi)存泄漏”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。