您好,登錄后才能下訂單哦!
本篇內容介紹了“nodejs如何檢查內存泄漏”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
node中可利用memwatch工具來檢查內存泄漏,方法:1、使用npm進行工具的安裝;2、在項目中添加“var memwatch=require('memwatch');memwatch.setup();”代碼;3、監聽leak事件即可。
本教程操作環境:windows7系統、nodejs 12.19.0版,DELL G3電腦。
追蹤Node.js代碼中的內存泄漏一直是一個很有挑戰的難題。本文討論如何從一個node寫的應用里自動的跟蹤到內存泄漏問題,在這里筆者向大家推薦兩款追查內存問題的神器 —— memwatch 和 heapdump
首先,我們來看一個簡單的內存泄漏
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);
每一個請求我們增加了1000個導致泄漏的監聽器。如果我們在一個shell控制臺中執行以下命令:
while true; do curl http://127.0.0.1:1337/; done
然后在另外一個shell控制臺中查看我們的進程
top -pid
我們會看到node進程產生異常高的內存占用,我們的node進程看起來失控了。那么,當我們的node進程出現這種情況的時候,通常我們該怎樣診斷出問題的根源?
npm模塊 memwatch 是一個非常好的內存泄漏檢查工具,讓我們先將這個模塊安裝到我們的app中去,執行以下命令:
npm install --save memwatch
然后,在我們的代碼中,添加:
var memwatch = require('memwatch'); memwatch.setup();
然后監聽 leak 事件
memwatch.on('leak', function(info) { console.error('Memory leak detected: ', info); });;
這樣當我們執行我們的測試代碼,我們會看到下面的信息:
{ 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發現了內存泄漏!memwatch 判定內存泄漏事件發生的規則如下:
當你的堆內存在5個連續的垃圾回收周期內保持持續增長,那么一個內存泄漏事件被派發
了解更加詳細的內容,查看 memwatch
使用memwatch我們發現了存在內存泄漏,這非常好,但是現在呢?我們還需要定位內存泄漏出現的實際位置。要做到這一點,有兩種方法可以使用。
通過memwatch你可以得到堆內存使用量和內存隨程序運行產生的差異。詳細的文檔在這里
例如,我們可以在兩個leak事件發生的間隔中做一個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; } });
執行這段代碼會輸出更多的信息:
{ 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' }, ...
所以在內存泄漏事件之間,我們發現堆內存增長了2.47MB,而導致內存增長的罪魁禍首是閉包。如果你的泄漏是由某個class造成的,那么what
字段可能會輸出具體的class名字,所以這樣的話,你會獲得足夠的信息來幫助你最終定位到泄漏之處。
然而,在我們的例子中,我們唯一獲得的信息只是泄漏來自于閉包,這個信息非常有用,但是仍不足以在一個復雜的應用中迅速找到問題的來源(復雜的應用往往有很多的閉包,不知道哪一個造成了內存泄漏——譯者注)
所以我們該怎么辦呢?這時候該Heapdump出場了。
npm模塊node-heapdump是一個非凡的模塊,它可以使用來將v8引擎的堆內存內容dump出來,這樣你就可以在Chrome的開發者工具中查看問題。你可以在開發工具中對比不同運行階段的堆內存快照,這樣可以幫助你定位到內存泄漏的位置。要想了解heapdump的更多內容,可以閱讀這篇文章
現在讓我們來試試 heapdump,在每一次發現內存泄漏的時候,我們都將此時的內存堆棧快照寫入磁盤中:
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); }); });
運行我們的代碼,磁盤上會產生一些.heapsnapshot
的文件到/tmp
目錄下。現在,在Chrome瀏覽器中,啟動開發者工具(在mac下的快捷鍵是alt+cmd+i),點擊Profiles
標簽并點擊Load
按鈕載入我們的快照。
我們能夠很清晰地發現原來leakyfunc()是內存泄漏的元兇。
我們依然還可以通過對比兩次記錄中heapdump的不同來更加迅速確認兩次dump之間的內存泄漏:
想要進一步了解開發者工具的memory profiling
功能,可以閱讀 Taming The Unicorn: Easing JavaScript Memory Profiling In Chrome DevTools 這篇文章。
我們給Turbo - FeedHenry開發的測試工具提交了一個小補丁 — 使用了上面所說的內存泄漏檢查技術。這樣就可以讓開發者寫針對內存的單元測試了,如果模塊有內存問題,那么測試結果中就會產生相應的警告。詳細了解具體的內容,可以訪問Turbo模塊。
“nodejs如何檢查內存泄漏”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。