女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

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

3天內不再提示

Node.js 內存泄漏問題初探

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

作者 | 后端Team朱捷峰

整理 | 包包

V8 垃圾回收機制

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

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

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

? 代碼區:實際正在運行的代碼

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

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


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

memory usage

{

rss: 4935680,

heapTotal: 1826816,

heapUsed: 650472,

external: 49879

}

以上數值以字節為單位

? rss:表示 Resident Set 的大小

? heapTotal:表示堆的總大小

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

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

我們知道在 Node.js 的運行時中,JavaScript 是由 V8 編譯成可執行的機器碼。運行時的數據結構是由 V8 來管理的,我們能做的很有限。通過 JavaScript 我們是沒法做到分配內存和釋放內存的。

V8 的垃圾回收算法實現還是很復雜的,感興趣的同學可以參考:http://newhtml.net/v8-garbage-collection/。但是我們仍然可以把原理簡單抽象:如果一個內存片段沒有被任何地方引用,我們可以假設它不再會被用到,那么該內存片段可以被釋放。


上圖表示在內存中各個對象的引用情況,只有當紅球對象不再被任何對象引用的時候,它才能被回收。

異常情況

既然 V8 會進行垃圾回收,那我們為什么還要關心內存情況呢?

理想情況,內存占用會保持在一個相對穩定的范圍:


實際上,我們仍然可能會看到內存占用升高的情況:


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

制造內存泄漏

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

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

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 在每次調用 replaceThing() 時會被重寫。問題就在于,someMethod 有閉包作用域作為上下文,這就意味著當調用 someMethod 時,unused 是可見的。雖然實際上 unused 并沒有被調用,但是它卻阻止了 V8 垃圾回收機制對 originalThing 進行回收。這就是我們平時所說的“循環引用”:


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

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

排查問題

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

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


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


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


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


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


第三步,重復上述過程,檢查內存泄漏問題是否解決。

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


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內存
    +關注

    關注

    8

    文章

    3108

    瀏覽量

    74983
  • NODE.JS
    +關注

    關注

    1

    文章

    49

    瀏覽量

    33062
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    HarmonyOS5云服務技術分享--ArkTS開發Node環境

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

    HarmonyOS5云服務技術分享--云函數創建配置指南

    指南 ??ZIP包上傳失敗??:檢查文件結構!Node.js/Python的入口文件必須放根目錄,Java的包路徑要和代碼一致。 ??內存不足報錯??:函數處理大文件時,內存選4GB更保險
    發表于 05-22 17:08

    KaihongOS操作系統:開發環境搭建

    ”。 步驟 2選擇 Do not import settings,點擊 OK。 步驟 3安裝 Node.js 與 ohpm。可以指定本地已安裝的 Node.js 或 ohpm 路徑位置;如果本地 沒有合適
    發表于 04-23 07:27

    在樹莓派上構建和部署 Node.js 項目

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

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

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

    內存泄漏檢測工具Sanitizer介紹

    內存泄漏,我們經常會遇到,如何檢測內存泄漏,除了我們之前講過的 valgrind,還可以使用 gcc 自帶的工具 sanitizer。
    的頭像 發表于 03-01 14:52 ?535次閱讀

    Bun 1.2震撼發布:全力挑戰Node.js生態的JavaScript運行時新星

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

    使用OpenVINO? ElectronJS中創建桌面應用程序

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

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

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

    前端技術探秘-Nodejs的CommonJS規范實現原理

    了解Node.js Node.js是一個基于ChromeV8引擎的JavaScript運行環境,使用了一個事件驅動、非阻塞式I/O模型,讓JavaScript 運行在服務端的開發平臺,它讓
    的頭像 發表于 11-05 11:56 ?1134次閱讀
    前端技術探秘-Nodejs的CommonJS規范實現原理

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

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

    ARMxy ARM 物聯網邊緣計算網關支持 Node-RED 用于工業控制

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

    如何檢測內存泄漏

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

    NONOS 1.5.3/1.5.4 SSL內存泄漏的原因?

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

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

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