伦伦影院久久影视,天天操天天干天天射,ririsao久久精品一区 ,一本大道香蕉大久在红桃,999久久久免费精品国产色夜,色悠悠久久综合88,亚洲国产精品久久无套麻豆,亚洲香蕉毛片久久网站,一本一道久久综合狠狠老

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 垃圾回收的原理。平常我們在編碼的時候也要注意盡量避免產生循環引用,但是如果遇到了也不要擔心,可以通過上面的步驟排查解決。


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

    關注

    9

    文章

    3223

    瀏覽量

    76469
  • NODE.JS
    +關注

    關注

    1

    文章

    49

    瀏覽量

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

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    OpenClaw搭建教程:云服務器一鍵部署完整流程

    基于Node.js運行的開源AIAgent框架,因此部署方式和很多Node.js應用類似。只要具備一臺Linux云服務器,并安裝Node.js環境,就可以完成OpenClaw的部署。根據官方文檔的說明
    的頭像 發表于 03-12 14:39 ?569次閱讀

    大模型 ai coding 比較

    Core i7-1195G7 @ 2.90GHz (4核8線程) OS Windows 10 (win32 x64) Node.js v24.13.0 測試日期 2026-02-19 網關
    發表于 02-19 13:43

    Docker容器化部署完全指南

    我們團隊從 2019 年開始全面容器化,目前線上跑著 800+ 個容器,覆蓋 Java、Go、Node.js、Python 四種技術棧。這篇文章把從安裝到生產環境踩過的坑全部整理出來。
    的頭像 發表于 02-09 14:09 ?589次閱讀

    從零開始安裝并配置開源AI編程神器OpenCode

    編程神器OpenCode吧! 一,第一步:環境準備 (Node.js & opencode 然后鍵入命令,“/connect",連接編程大模型供應商。 選擇“Z.AI Coding Plan”,如下所示
    的頭像 發表于 01-22 21:22 ?1774次閱讀
    從零開始安裝并配置開源AI編程神器OpenCode

    從0到1搭建實時日志監控系統:基于WebSocket + Elasticsearch的實戰方案

    低成本、實時性高的日志監控系統。 2. 技術選型 數據存儲 :Elasticsearch(高效檢索與聚合) 實時推送 :WebSocket(全雙工通信,避免HTTP輪詢) 后端服務 :Node.js
    發表于 01-09 16:43

    WebGL/Canvas 內存泄露分析

    在構建高性能、長周期運行的 WebGL/Canvas 應用(如 3D 編輯器、數據可視化平臺)時,內存管理是一個至關重要且極具挑戰性的課題。 開發者通常面臨的內存泄漏問題,其根源遠比簡單
    的頭像 發表于 10-21 11:40 ?510次閱讀
    WebGL/Canvas <b class='flag-5'>內存</b>泄露分析

    at_device 包 ml307長時間運行有內存泄漏問題怎么解決?

    使用 at_device 包中的 ml307 包長時間運行有大量內存泄漏問題,大概漲了20K,求助解決。
    發表于 09-24 07:41

    進迭時空 V8 RISC-V 后端優化

    前言V8是Google開發及開源的JavaScript和WebAssembly語言編譯引擎,是Chromium項目的一部分,主要應用于Chrome瀏覽器和Node.js等項目,在瀏覽器生態中發
    的頭像 發表于 07-31 09:02 ?1660次閱讀
    進迭時空 V8 RISC-V 后端優化

    【M-K1HSE開發板免費體驗】M-K1HSE開發板構建HELLO WORLD頁面

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

    在OpenVINO? C++代碼中啟用 AddressSanitizer 時的內存泄漏怎么解決?

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

    HarmonyOS5云服務技術分享--ArkTS開發函數

    等打包 ? 支持Node.js 14.x/18.x和Java 1.8 ? 支持HTTP觸發器調用 ? 持續開發調試一條龍 ?? 準備工作: 安裝AGCLI工具(華為應用分發服務命令行工具) 準備測試
    發表于 05-22 17:29

    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

    keithley 2600系列labiew vi中配置測量功能中的node in 和node out具體功能是什么?

    圖中的node in和node out的具體作用是什么呢?新手剛剛接觸labview和源表,不太明白其具體功能
    發表于 05-12 10:11

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

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