元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
浏览器架构概览
多进程架构设计
浏览器内核组成
进程间通信机制
沙箱安全机制
浏览器加载页面流程
▶
渲染引擎原理
HTML解析算法
CSSOM构建过程
布局计算原理
图层合成机制
重绘与回流优化
▶
JavaScript引擎
V8执行流水线
事件循环机制
内存管理策略
JIT编译原理
垃圾回收算法
▶
网络栈实现
HTTP协议栈
缓存机制详解
资源加载策略
WebSocket实现
网络安全机制
▶
浏览器存储
Cookie管理机制
Web Storage实现
IndexedDB原理
缓存存储策略
▶
浏览器安全
同源策略实现
发布时间:
2025-03-23 15:39
↑
☰
# JavaScript垃圾回收算法 ## 概述 垃圾回收(Garbage Collection, GC)是JavaScript引擎自动管理内存的核心机制。本文将详细介绍现代JavaScript引擎中使用的垃圾回收算法及其实现原理。 ## 基础概念 ### 1. 可达性分析 #### 根对象 - 全局对象 - 当前函数的局部变量和参数 - 闭包中的变量 - 正在执行的事件处理函数 #### 可达性判定 ```javascript // 可达对象示例 let user = { name: "John" }; let admin = user; // admin也可达 user = null; // user引用被切断,但对象仍可通过admin访问 ``` ### 2. 内存泄漏 #### 常见场景 ```javascript // 全局变量泄漏 function leak() { leakedVariable = "I am leaked"; // 未使用var/let/const } // 闭包泄漏 function createLeak() { const largeData = new Array(1000000); return function() { console.log(largeData[0]); // largeData被持有 }; } ``` ## 回收算法 ### 1. 标记-清除算法 #### 工作原理 - 标记阶段:从根开始遍历,标记所有可达对象 - 清除阶段:清除所有未标记对象 - 内存整理:处理内存碎片 #### 实现示例 ```javascript // 模拟标记-清除过程 class GarbageCollector { constructor() { this.heap = new Map(); this.marks = new Set(); } mark(root) { if (this.marks.has(root)) return; this.marks.add(root); // 递归标记所有引用 const refs = this.heap.get(root) || []; refs.forEach(ref => this.mark(ref)); } sweep() { for (const obj of this.heap.keys()) { if (!this.marks.has(obj)) { this.heap.delete(obj); // 清除未标记对象 } } this.marks.clear(); } } ``` ### 2. 分代回收 #### 新生代 - Scavenge算法 - From空间和To空间 - 对象晋升机制 #### 老生代 - 标记-整理算法 - 增量标记 - 并发回收 ### 3. 增量回收 #### 工作原理 ```javascript // 增量标记示例 class IncrementalMarking { constructor() { this.markingState = 'idle'; this.markingQueue = []; this.markingBudget = 5; // ms } markIncrementally() { const startTime = performance.now(); while (this.markingQueue.length > 0) { if (performance.now() - startTime > this.markingBudget) { // 超出时间预算,暂停标记 requestIdleCallback(() => this.markIncrementally()); return; } const obj = this.markingQueue.pop(); this.mark(obj); } this.finishMarking(); } } ``` ## 性能优化 ### 1. 写屏障 #### 原理实现 ```javascript // 写屏障示例 class WriteBarrier { constructor() { this.remembered = new Set(); } write(obj, field, value) { if (this.isOldGeneration(obj) && this.isNewGeneration(value)) { this.remembered.add(obj); } obj[field] = value; } isOldGeneration(obj) { // 判断对象是否在老生代 return obj.age > 2; } isNewGeneration(obj) { // 判断对象是否在新生代 return obj.age <= 2; } } ``` ### 2. 并发回收 #### 实现机制 ```javascript // 并发回收示例 class ConcurrentGC { constructor() { this.gcState = 'idle'; this.markingWorker = null; } startConcurrentMarking() { this.gcState = 'marking'; this.markingWorker = new Worker('marking.js'); this.markingWorker.onmessage = (e) => { if (e.data.type === 'markingComplete') { this.finalizeConcurrentMarking(); } }; } finalizeConcurrentMarking() { // 完成标记后的清理工作 this.gcState = 'sweeping'; this.sweep(); this.gcState = 'idle'; } } ``` ## 调试与分析 ### 1. 内存分析 #### Chrome DevTools - 堆快照 - 分配时间线 - 内存泄漏定位 #### Node.js工具 ```javascript // 堆分析示例 const heapdump = require('heapdump'); function analyzeMemory() { heapdump.writeSnapshot((err, filename) => { console.log('Heap dump written to:', filename); }); } // 定期生成堆转储 setInterval(analyzeMemory, 30000); ``` ### 2. 性能监控 #### GC监控 ```javascript // GC性能监控 const gc = new PerformanceObserver((list) => { const entries = list.getEntries(); entries.forEach(entry => { console.log({ type: entry.name, duration: entry.duration, startTime: entry.startTime }); }); }); gc.observe({ entryTypes: ['gc'] }); ``` #### 内存使用监控 ```javascript // 内存使用监控 function monitorMemory() { if (performance.memory) { console.log({ usedJSHeapSize: performance.memory.usedJSHeapSize, totalJSHeapSize: performance.memory.totalJSHeapSize, jsHeapSizeLimit: performance.memory.jsHeapSizeLimit }); } } setInterval(monitorMemory, 1000); ``` ## 最佳实践 ### 1. 内存优化 - 及时释放不再使用的引用 - 避免意外的全局变量 - 注意闭包导致的内存泄漏 - 使用弱引用存储缓存数据 - 大数据处理时使用流式操作 ### 2. GC优化 - 控制对象生命周期 - 避免频繁创建临时对象 - 合理使用对象池 - 注意DOM节点的及时释放 - 使用适当的数据结构