chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

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

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

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

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

張康康 ? 2018-11-01 13:39 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

作者 | 后端Team朱捷峰

整理 | 包包

V8 垃圾回收機(jī)制

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

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

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

? 代碼區(qū):實(shí)際正在運(yùn)行的代碼

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

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


在 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:表示堆的實(shí)際使用大小

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

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

V8 的垃圾回收算法實(shí)現(xiàn)還是很復(fù)雜的,感興趣的同學(xué)可以參考:http://newhtml.net/v8-garbage-collection/。但是我們?nèi)匀豢梢园言砗?jiǎn)單抽象:如果一個(gè)內(nèi)存片段沒有被任何地方引用,我們可以假設(shè)它不再會(huì)被用到,那么該內(nèi)存片段可以被釋放。


上圖表示在內(nèi)存中各個(gè)對(duì)象的引用情況,只有當(dāng)紅球?qū)ο蟛辉俦蝗魏螌?duì)象引用的時(shí)候,它才能被回收。

異常情況

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

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


實(shí)際上,我們?nèi)匀豢赡軙?huì)看到內(nèi)存占用升高的情況:


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

制造內(nèi)存泄漏

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

在這篇文章里,我們就不一一列舉所有可能產(chǎn)生問題的錯(cuò)誤情況。我們來看一下一個(gè)難以排查的情況,代碼很簡(jiǎn)單,你可以自己運(yù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() 時(shí)會(huì)被重寫。問題就在于,someMethod 有閉包作用域作為上下文,這就意味著當(dāng)調(diào)用 someMethod 時(shí),unused 是可見的。雖然實(shí)際上 unused 并沒有被調(diào)用,但是它卻阻止了 V8 垃圾回收機(jī)制對(duì) originalThing 進(jìn)行回收。這就是我們平時(shí)所說的“循環(huán)引用”:


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

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

排查問題

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

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


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


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


第一步,先選擇 Profiles 中的第二個(gè)文件,然后篩選 Objects 選項(xiàng)選擇“Objects allocated between 1539255057342 and 1539255076968 ”,然后在 Constructor 中進(jìn)行具體的分析 。


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


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

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


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

    關(guān)注

    8

    文章

    3156

    瀏覽量

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

    關(guān)注

    1

    文章

    49

    瀏覽量

    33587
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    at_device 包 ml307長(zhǎng)時(shí)間運(yùn)行有內(nèi)存泄漏問題怎么解決?

    使用 at_device 包中的 ml307 包長(zhǎng)時(shí)間運(yùn)行有大量內(nèi)存泄漏問題,大概漲了20K,求助解決。
    發(fā)表于 09-24 07:41

    【M-K1HSE開發(fā)板免費(fèi)體驗(yàn)】M-K1HSE開發(fā)板構(gòu)建HELLO WORLD頁(yè)面

    工程存放的位置,其他參數(shù)保持默認(rèn)設(shè)置即可,點(diǎn)擊【finish 】。 其中Node用來配置當(dāng)前工程運(yùn)行的Node.js版本,可選擇使用已有的Node.js或下載新的Node.js版本 4
    發(fā)表于 07-15 04:31

    在OpenVINO? C++代碼中啟用 AddressSanitizer 時(shí)的內(nèi)存泄漏怎么解決?

    在 OpenVINO? C++代碼中啟用 AddressSanitizer 時(shí)遇到內(nèi)存泄漏: \"#0 0xaaaab8558370 in operator new(unsigned
    發(fā)表于 06-23 07:16

    HarmonyOS5云服務(wù)技術(shù)分享--ArkTS開發(fā)函數(shù)

    等打包 ? 支持Node.js 14.x/18.x和Java 1.8 ? 支持HTTP觸發(fā)器調(diào)用 ? 持續(xù)開發(fā)調(diào)試一條龍 ?? 準(zhǔn)備工作: 安裝AGCLI工具(華為應(yīng)用分發(fā)服務(wù)命令行工具) 準(zhǔn)備測(cè)試
    發(fā)表于 05-22 17:29

    HarmonyOS5云服務(wù)技術(shù)分享--ArkTS開發(fā)Node環(huán)境

    ? 你好呀,開發(fā)者小伙伴們!今天我們來聊聊如何在HarmonyOS(ArkTS API 9及以上)中玩轉(zhuǎn)云函數(shù),特別是結(jié)合Node.js和HTTP觸發(fā)器的開發(fā)技巧。文章會(huì)手把手帶你從零開始,用最接地
    發(fā)表于 05-22 17:21

    HarmonyOS5云服務(wù)技術(shù)分享--云函數(shù)創(chuàng)建配置指南

    指南 ??ZIP包上傳失敗??:檢查文件結(jié)構(gòu)!Node.js/Python的入口文件必須放根目錄,Java的包路徑要和代碼一致。 ??內(nèi)存不足報(bào)錯(cuò)??:函數(shù)處理大文件時(shí),內(nèi)存選4GB更保險(xiǎn)
    發(fā)表于 05-22 17:08

    KaihongOS操作系統(tǒng):開發(fā)環(huán)境搭建

    ”。 步驟 2選擇 Do not import settings,點(diǎn)擊 OK。 步驟 3安裝 Node.js 與 ohpm??梢灾付ū镜匾寻惭b的 Node.js 或 ohpm 路徑位置;如果本地 沒有合適
    發(fā)表于 04-23 07:27

    在樹莓派上構(gòu)建和部署 Node.js 項(xiàng)目

    探索在RaspberryPi上構(gòu)建和部署Node.js項(xiàng)目的最佳實(shí)踐。通過我們的專業(yè)提示和技巧,克服常見挑戰(zhàn),使您的項(xiàng)目順利運(yùn)行。去年圣誕節(jié),我收到了一份極其令人著迷的禮物,它占據(jù)了我許多周末的時(shí)間
    的頭像 發(fā)表于 03-25 09:44 ?432次閱讀
    在樹莓派上構(gòu)建和部署 <b class='flag-5'>Node.js</b> 項(xiàng)目

    【干貨】什么是Node-RED?一文帶你了解!

    一什么是Node-RED?首先我們來認(rèn)識(shí)一下什么是Node-RED。Node-RED是一個(gè)基于Node.js的開源可視化編程工具,于2013年由IBM公司推出。它可以通過瀏覽器的圖形化
    的頭像 發(fā)表于 03-13 19:32 ?1315次閱讀
    【干貨】什么是<b class='flag-5'>Node</b>-RED?一文帶你了解!

    內(nèi)存泄漏檢測(cè)工具Sanitizer介紹

    內(nèi)存泄漏,我們經(jīng)常會(huì)遇到,如何檢測(cè)內(nèi)存泄漏,除了我們之前講過的 valgrind,還可以使用 gcc 自帶的工具 sanitizer。
    的頭像 發(fā)表于 03-01 14:52 ?1121次閱讀

    Bun 1.2震撼發(fā)布:全力挑戰(zhàn)Node.js生態(tài)的JavaScript運(yùn)行時(shí)新星

    了與 Node.js 的兼容性,還為開發(fā)者帶來了內(nèi)置的數(shù)據(jù)庫(kù)支持和云服務(wù)集成能力,進(jìn)一步強(qiáng)化了其“全能工具包”的定位。Node.js 兼容性獲得突破性進(jìn)展在此次更新中,最引人注目的是 Bun 在 Node.js 兼容性
    的頭像 發(fā)表于 01-24 10:42 ?1181次閱讀
    Bun 1.2震撼發(fā)布:全力挑戰(zhàn)<b class='flag-5'>Node.js</b>生態(tài)的JavaScript運(yùn)行時(shí)新星

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

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

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

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

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

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

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

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