Node进阶
Node內存管理和垃圾回收
node.js 是基于 V8 引擎的 javascript 運行環境。
V8 引擎
javascript 代碼運行的時候提供編譯優化、內存管理、垃圾回收等功能
代碼編譯優化:
1、通過 parser 將 javascript 源碼轉為 ast 抽象語法樹
2、將 ast 抽象語法樹轉為字節碼,
3、然后轉為機器可運行的匯編代碼
內存管理:管理內存分配、內存劃分
垃圾回收:通過垃圾回收機制對無用代碼釋放內存
內存管理
類型
常駐內存:運行 node 進程時候的所有內存( 代碼占用內存、棧內存、堆內存、堆外內存 )
棧內存:用于存放變量( javascript 中基本類型 )
堆內存:用于存放對象、閉包引用上下文( 引用類型 )
堆外內存:不是通過 V8 分配,不受V8管理,不占用V8內存。一些用于存放 buffer 數據的 ( buffer 對象依然在堆內存中 )
限制
默認給堆內存分配的大小:64位系統為 1.4G、32位系統為 0.7G
可以通過 node 啟動命令修改內存大小。
不過分配的內存越大,垃圾回收一次的時間越長
內存信息獲取
node 提供了 process.memoryUsage() 獲取當前進程的內存信息
rss :常駐內存大小( 進程分配的內存 )
heapTotal:給 V8 分配的內存大小
heapUsed:已使用的堆內存大小
external:堆外使用的內存( buffer )
1、內存溢出和堆外內存
const fs = require('fs')
const format = function (item, type = 0) {
let ext = 'byte'
switch (type) {
case 1:
ext = 'KB'
break;
case 2:
ext = 'M'
break;
case 3:
ext = 'G'
break;
case 3:
ext = 'T'
break;
}
if (item < 1024) return item.toFixed(2) + ext
return format(item / 1024, type + 1)
}
function showMemory() {
const memoryUsage = process.memoryUsage()
console.log(`---------------------`)
for (const item in memoryUsage) {
console.log(`${item}:${format(memoryUsage[item])}`)
}
}
showMemory()
// 使用 40M 堆外內存
const buffer = new ArrayBuffer(40 * 1024 * 1024)
const total = []
setInterval(() => {
// 20M 內存的添加
total.push(new Array(20 * 1024 * 1024))
showMemory()
},2000)
垃圾回收
釋放一些在應用程序中不在被引用,或者空指針的一些變量的內存。
1、變量為空的時候釋放內存棧
2、對象結束沒引用或者引用的對象被清除的時候釋放對應內存( 對象無法被根節點訪問時候 )
堆內存中的分類
新生代:內存比較小,未經歷垃圾回收的對象存放位置
from 區:回收檢查( 算法回收 ) 的時候,檢查區
to 區:回收檢查( 算法回收 ) 的時候,from檢查到對象被引用存活了
老生代:內存是新生代20倍,from 區收檢查( 算法回收 ) 的時候,已經經歷過的對象或者to區滿了時候送到老生代
新生代垃圾回收
新生代垃圾回收是通過交換 from 區和 to 區來實現的
1、新建的對象被存放在 from 區,滿了之后執行新生代垃圾回收檢查
2、檢查 from 區對象,如果已經經歷過一次檢查且依然被引用的對象送到老生代區
3、檢查 from 區對象,如果被引用則總到 to 區,to 區滿了25%則送到老生代區
4、結束 from 檢查后,交換 from 區和 to 區身份( from 區變 to區,反之 )
5、再次檢查,回到 1。
老生代垃圾回收
老生代垃圾回收沒有新生代頻繁
主要通過判斷是否被引用進行標記清除,然后對存活的對象整理
1、檢查老生代區,是否被引用,未被引用,釋放該內存塊的內存
2、將依舊存活的對象,整理到老生代區的一端
3、清除存活一端以外部分的內存塊
堆內存里面的對象主要是靠引用計數來判斷是否釋放內存(每引用一次增加1)
內存泄漏場景
1、未釋放無用的全局變量/對象
2、閉包的上下文
function add() {
const x = 1;
const y = 2;
return function (a) {
return y + 2
}
}
const add1 = add();
/*
* 執行 add() 后
* x 將會被釋放
* y 將存在 add1 的上下文中,不會被釋放( 除非 add1 = null )
* */
3、緩存大量數據
// 分成小的一部分一部分處理 const array = new Array(20 * 1024 * 1024)
內存分析工具
利用內存檢查工具(node-heapdump、node-profiler) 生成內存快照
利用 chrome 進行分析。
總結
- 上一篇: 如何查询电脑是正版如何查电脑版本
- 下一篇: 「经验分享」芹菜炒肉芹菜要焯水吗