色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Node.js 內(nèi)存泄漏問題初探

張康康 ? 2018-11-01 13:39 ? 次閱讀

作者 | 后端Team朱捷峰

整理 | 包包

V8 垃圾回收機制

事實上,我們平時在寫 Node.js 的時候很少去關(guān)心內(nèi)存問題,那是因為 Node.js 對 Google V8 進行封裝,底層的垃圾收回機制都交給 V8 處理。大部分時候,是不會有內(nèi)存問題的。相對于 C/C++ 這類需要自己管理內(nèi)存的語言,Node.js 有更加平滑的學(xué)習(xí)曲線,這也是 Node.js 最大的優(yōu)勢之一。但是也總有意外情況,可能導(dǎo)致 Node.js 進程內(nèi)存泄漏。

那么如何避免我們的 Node.js 程序出現(xiàn)內(nèi)存泄漏的情況呢?我們先來了解下 V8 內(nèi)存管理機制。

一個進程通常是通過在內(nèi)存中分配空間來體現(xiàn)的,這個空間我們稱之為 Resident Set(常駐空間)。V8 將內(nèi)存分為了以下幾塊:

? 代碼區(qū):實際正在運行的代碼

? 棧區(qū):包含了所有的值類型(數(shù)字、布爾值等)、指向存儲在堆區(qū)的對象指針、定義程序控制流的指針

? 堆區(qū):專門用來存儲引用類型的內(nèi)存區(qū)域,比如對象、字符串和閉包


在 Node.js 中,我們可以通過調(diào)用process.memoryUsage() 方法來來查詢內(nèi)存使用情況。該函數(shù)返回值如下:

memory usage

{

rss: 4935680,

heapTotal: 1826816,

heapUsed: 650472,

external: 49879

}

以上數(shù)值以字節(jié)為單位

? rss:表示 Resident Set 的大小

? heapTotal:表示堆的總大小

? heapUsed:表示堆的實際使用大小

? external:表示 V8 管理的綁定到 JavaScript 對象的 C++ 對象的大小

我們知道在 Node.js 的運行時中,JavaScript 是由 V8 編譯成可執(zhí)行的機器碼。運行時的數(shù)據(jù)結(jié)構(gòu)是由 V8 來管理的,我們能做的很有限。通過 JavaScript 我們是沒法做到分配內(nèi)存和釋放內(nèi)存的。

V8 的垃圾回收算法實現(xiàn)還是很復(fù)雜的,感興趣的同學(xué)可以參考:http://newhtml.net/v8-garbage-collection/。但是我們?nèi)匀豢梢园言砗唵纬橄螅喝绻粋€內(nèi)存片段沒有被任何地方引用,我們可以假設(shè)它不再會被用到,那么該內(nèi)存片段可以被釋放。


上圖表示在內(nèi)存中各個對象的引用情況,只有當紅球?qū)ο蟛辉俦蝗魏螌ο笠玫臅r候,它才能被回收。

異常情況

既然 V8 會進行垃圾回收,那我們?yōu)槭裁催€要關(guān)心內(nèi)存情況呢?

理想情況,內(nèi)存占用會保持在一個相對穩(wěn)定的范圍:


實際上,我們?nèi)匀豢赡軙吹絻?nèi)存占用升高的情況:


V8 垃圾回收機制盡可能地回收和釋放內(nèi)存,但是每次執(zhí)行垃圾回收以后,內(nèi)存占用仍然持續(xù)上升,這明顯就是內(nèi)存泄漏了。

制造內(nèi)存泄漏

有一些很明顯的情況會導(dǎo)致內(nèi)存泄漏:1、比如將每位訪客的 IP 記錄在 global 上存儲數(shù)組上;2、再比如著名的“ 沃爾瑪內(nèi)存泄漏事件”,它是由 Node.js 核心代碼中一個遺漏的聲明引發(fā)的血案,工程師們花了好幾個星期去排查并最終得以解決。

在這篇文章里,我們就不一一列舉所有可能產(chǎn)生問題的錯誤情況。我們來看一下一個難以排查的情況,代碼很簡單,你可以自己運行調(diào)試:

memory leak demo

const express = require('express');

const app = express();

const port = 3000;

let theThing = null;

const replaceThing = function () {

let originalThing = theThing;

let unused = function () {

if (originalThing)

console.log("hi");

};

theThing = {

longStr: new Array(1000000).join('*'),

someMethod: function () {

console.log(someMessage);

}

};

};

app.get('/leak', (req, res) => {

replaceThing();

let memoryInfo = JSON.stringify(process.memoryUsage());

console.log(memoryInfo);

res.send(memoryInfo);

})

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

初看的話,這段代碼沒啥問題。我們可以想象 theThing 在每次調(diào)用 replaceThing() 時會被重寫。問題就在于,someMethod 有閉包作用域作為上下文,這就意味著當調(diào)用 someMethod 時,unused 是可見的。雖然實際上 unused 并沒有被調(diào)用,但是它卻阻止了 V8 垃圾回收機制對 originalThing 進行回收。這就是我們平時所說的“循環(huán)引用”:


既然找到問題所在,那么如何解決呢?答案很簡單,我們只要切斷循環(huán)引用就可以了,這里我們只需要在 replaceThing 這個方法最后加入 theThing = null。

針對這個問題,我們還可以通過 ESLint 的 no-unused-vars 規(guī)則來避免定義了但是未使用的變量,這樣可以減少循環(huán)引用的可能性。

排查問題

理解了垃圾回收的原理,那么我們平常在碼代碼的時候也要注意避免循環(huán)引用的情況出現(xiàn)。但是就像上面這種情況,有時候就是防不勝防。那么遇到問題的時候,我們應(yīng)該如何排查呢?

推薦一下我寫的一個小工具 heapsnapshot.js ,可以獲取生成堆的快照信息,如下圖:


然后利用 Chrome 開發(fā)者工具,Memory 來做具體分析:


請選擇相鄰的3個堆快照文件,導(dǎo)入 Memory 分析工具中,如下圖:


第一步,先選擇 Profiles 中的第二個文件,然后篩選 Objects 選項選擇“Objects allocated between 1539255057342 and 1539255076968 ”,然后在 Constructor 中進行具體的分析 。


第二步,同理對第二個和第三個文件進行對比分析。找到兩次分析都出現(xiàn)過的元素,重點排查,定位到具體的問題代碼,再做修改。


第三步,重復(fù)上述過程,檢查內(nèi)存泄漏問題是否解決。

以上只是對 Node.js 內(nèi)存問題的一個初步探討,感興趣的話推薦大家去看下 V8 垃圾回收的原理。平常我們在編碼的時候也要注意盡量避免產(chǎn)生循環(huán)引用,但是如果遇到了也不要擔(dān)心,可以通過上面的步驟排查解決。


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3028

    瀏覽量

    74100
  • NODE.JS
    +關(guān)注

    關(guān)注

    1

    文章

    47

    瀏覽量

    32781
收藏 人收藏

    評論

    相關(guān)推薦

    虛擬內(nèi)存溢出該怎么處理 虛擬內(nèi)存在服務(wù)器中的應(yīng)用

    、虛擬內(nèi)存溢出的原因 內(nèi)存泄漏 :程序中未正確釋放的內(nèi)存會導(dǎo)致內(nèi)存泄漏,隨著時間的推移,這些
    的頭像 發(fā)表于 12-04 09:49 ?173次閱讀

    使用OpenVINO? ElectronJS中創(chuàng)建桌面應(yīng)用程序

    ? 最近,我完成了一個 demo 演示,展示了 OpenVINO 在 Node.js 框架中的強大功能。得益于與 Electron.js 的集成,該演示不僅能夠高效地執(zhí)行神經(jīng)網(wǎng)絡(luò)推理,還提供了交互式
    的頭像 發(fā)表于 11-25 11:35 ?187次閱讀
    使用OpenVINO? ElectronJS中創(chuàng)建桌面應(yīng)用程序

    Node.js小科普和Node.js安裝常見管理工具

    Node.js是一個JavaScript的運行環(huán)境,用來執(zhí)行JavaScript代碼。 為什么會出現(xiàn)這么一個運行環(huán)境呢,從JavaScript研發(fā)初衷可以看出它是為了運行在瀏覽器中的,讓網(wǎng)頁交互更加
    的頭像 發(fā)表于 11-23 15:37 ?125次閱讀
    <b class='flag-5'>Node.js</b>小科普和<b class='flag-5'>Node.js</b>安裝常見管理工具

    前端技術(shù)探秘-Nodejs的CommonJS規(guī)范實現(xiàn)原理

    了解Node.js Node.js是一個基于ChromeV8引擎的JavaScript運行環(huán)境,使用了一個事件驅(qū)動、非阻塞式I/O模型,讓JavaScript 運行在服務(wù)端的開發(fā)平臺,它讓
    的頭像 發(fā)表于 11-05 11:56 ?797次閱讀
    前端技術(shù)探秘-Nodejs的CommonJS規(guī)范實現(xiàn)原理

    工程師必備!Node.js和常見管理工具介紹(附操作演示)

    語言及其相關(guān)生態(tài)中的一些基礎(chǔ)而關(guān)鍵的概念,以及它們是如何在互聯(lián)網(wǎng)歷史浪潮中產(chǎn)生的。一JavaScript與Node.js1JavaScriptJavaScript,即JS
    的頭像 發(fā)表于 08-30 12:34 ?319次閱讀
    工程師必備!<b class='flag-5'>Node.js</b>和常見管理工具介紹(附操作演示)

    ARMxy ARM 物聯(lián)網(wǎng)邊緣計算網(wǎng)關(guān)支持 Node-RED 用于工業(yè)控制

    在惡劣環(huán)境下穩(wěn)定運行。豐富的通信接口(如網(wǎng)口、USB、RS485 等)及 WiFi/4G 支持,使網(wǎng)關(guān)能夠靈活適應(yīng)不同網(wǎng)絡(luò)環(huán)境。 Node-RED 是一個基于 Node.js 的流程編排工具,通過
    的頭像 發(fā)表于 08-19 17:01 ?389次閱讀
    ARMxy ARM 物聯(lián)網(wǎng)邊緣計算網(wǎng)關(guān)支持 <b class='flag-5'>Node</b>-RED 用于工業(yè)控制

    如何檢測內(nèi)存泄漏

    檢測內(nèi)存泄漏是軟件開發(fā)過程中一項至關(guān)重要的任務(wù),它有助于識別和解決那些導(dǎo)致程序占用過多內(nèi)存資源,從而影響程序性能甚至導(dǎo)致程序崩潰的問題。以下將詳細闡述幾種常見的內(nèi)存
    的頭像 發(fā)表于 07-30 11:50 ?1983次閱讀

    NONOS 1.5.3/1.5.4 SSL內(nèi)存泄漏的原因?

    我已經(jīng)通過隨附的代碼驗證了當發(fā)生 SSL 握手錯誤時,會生成內(nèi)存泄漏 此外,espconn_reconnect_callback不稱為信令ESPCONN_HANDSHAKE - TCP SSL 握手
    發(fā)表于 07-18 07:24

    使用system_show_malloc()檢查內(nèi)存泄漏遇到異常怎么解決?

    我想使用system_show_malloc()檢查內(nèi)存泄漏,但是當我調(diào)用該函數(shù)時,我得到了致命的異常: 致命異常 28 (LoadProhibitedCause): epc1
    發(fā)表于 07-10 06:32

    鴻蒙開發(fā)實戰(zhàn):網(wǎng)絡(luò)請求庫【axios】

    [Axios]?,是一個基于 promise 的網(wǎng)絡(luò)請求庫,可以運行 node.js 和瀏覽器中。本庫基于[Axios]原庫v1.3.4版本進行適配,使其可以運行在 OpenHarmony,并沿用其現(xiàn)有用法和特性。
    的頭像 發(fā)表于 03-25 16:47 ?3910次閱讀
    鴻蒙開發(fā)實戰(zhàn):網(wǎng)絡(luò)請求庫【axios】

    C語言內(nèi)存泄漏問題原理

    內(nèi)存泄漏問題只有在使用堆內(nèi)存的時候才會出現(xiàn),棧內(nèi)存不存在內(nèi)存泄漏問題,因為棧
    發(fā)表于 03-19 11:38 ?530次閱讀
    C語言<b class='flag-5'>內(nèi)存</b><b class='flag-5'>泄漏</b>問題原理

    【鴻蒙】webview內(nèi)存泄漏問題的分析報告

    1 關(guān)鍵字 webview;內(nèi)存泄漏 2 問題描述 問題現(xiàn)象:在 3.1release 版本和 3.2bete1 版本中,在 RK3568 上使用 etsWeb 和其他瀏覽器時,webview 所占
    的頭像 發(fā)表于 03-02 15:12 ?2169次閱讀

    鴻蒙 Harmony 工具篇

    平臺做的自定義 IDE。因此,對于 Java 開發(fā)者而言,DevEco 只是“在熟悉中帶有一點點陌生”。 安裝 Node.js 在安裝好 DevEco 之后,首次點開需要開發(fā)者設(shè)置 Node.js
    的頭像 發(fā)表于 01-30 15:00 ?1194次閱讀
    鴻蒙 Harmony 工具篇

    鴻蒙OpenHarmony NAPI技術(shù)-基礎(chǔ)學(xué)習(xí)

    NAPI(Native API)是OpenHarmony系統(tǒng)中的一套原生模塊擴展開發(fā)框架,它基于Node.js N-API規(guī)范開發(fā),為開發(fā)者提供了JavaScript與C/C++模塊之間相互調(diào)用的交互能力。可以在NodeJs官網(wǎng)查看各種NAPI接口定義說明。
    的頭像 發(fā)表于 01-19 16:57 ?989次閱讀
    鴻蒙OpenHarmony NAPI技術(shù)-基礎(chǔ)學(xué)習(xí)

    鴻蒙開發(fā)環(huán)境搭建-高頻環(huán)境問題解決

    1.Node版本問題 由于SDK的部分工具依賴Node.js運行時,推薦使用配套API版本的Node.js,保證工程的兼容性。 匹配關(guān)系見下表: API Level Node.js支持
    發(fā)表于 01-12 22:29
    主站蜘蛛池模板: 免费国产精品视频| 久久偷拍国2017| 92看看福利午夜影院| 亚洲精品婷婷无码成人A片在线 | 十九禁啊啪射视频在线观看 | 97免费在线视频| 在线一本码道高清| 又粗又大又爽又黄的免费视频| 亚洲高清无在码在线电影| 无限资源在线看影院免费观看| 色婷婷狠狠97成为人免费| 日韩 无码 手机 在线| 日本熟妇乱妇熟色A片蜜桃亚洲 | 伊人色综合久久大香| 一二三四电影完整版免费观看| 亚洲精品天堂在线| 亚洲视频91| 伊人久久青草青青综合| 伊人网伊人网| 最新国产av.在线视频| 最近的2019中文字幕国语HD| 4480yy午夜私人影院| 99热在线观看精品| 成人免费在线观看视频| 岛国大片在线播放免费| 国产国拍亚洲精品av麻豆| 国产精品亚洲专一区二区三区| 国产亚洲精品首页在线播放| 狠狠色噜噜狠狠狠狠米奇777| 九九热在线免费观看| 两百磅美女| 欧美香蕉大胸在线视频观看| 人妖xxhdxx| 小蝌蚪视频在线观看免费观看WWW| 亚洲高清视频免费| 色内射无码AV| 午夜一区二区三区| 亚洲欧美中文字幕5发布| 最新果冻传媒在线观看免费版| AV天堂午夜精品蜜臀AV| 国产成人精品视频频|