无需登录 数据私有 本地保存

内存泄漏模拟器 - 故意创建泄漏并观察堆增长

26
0
0
0

内存泄漏模拟器

模拟不同类型的内存泄漏,实时观察堆内存增长趋势

当前堆使用量
--
正在采样...
活跃泄漏数
0
无活跃泄漏
预估泄漏内存
0 B
累计泄漏量
堆增长率
0 B/s
近10秒平均
堆使用量 预估泄漏量 泄漏计数(x10)
添加模拟泄漏
MB
ms
活跃泄漏列表 0
暂无活跃泄漏,内存状态健康
常见问题与知识点
内存泄漏是指程序在运行过程中分配的内存未能被及时释放,导致可用内存逐渐减少的现象。在JavaScript中,垃圾回收器(GC)会自动回收不再使用的内存,但如果代码中存在对不再需要使用的对象的持续引用,GC就无法回收这些内存,从而造成泄漏。长期运行的应用(如SPA、Node.js服务)中,内存泄漏会导致性能下降甚至崩溃。
常见类型包括:① 全局变量泄漏——未使用var/let/const声明,意外创建全局变量;② 闭包泄漏——闭包持有外部作用域的大对象引用;③ 定时器泄漏——setInterval/setTimeout未清理,回调持有DOM或数据引用;④ DOM引用泄漏——移除DOM节点后JS仍持有其引用;⑤ 事件监听器泄漏——未移除的事件监听器持有DOM引用;⑥ Map/Set泄漏——使用对象作为键且未清理。
打开Chrome DevTools → Performance面板 → 录制页面操作 → 观察JS Heap(蓝色线)是否持续上升且在手动GC后不下降。也可使用Memory面板:① 拍摄Heap Snapshot对比前后差异;② 使用Allocation instrumentation on timeline记录内存分配时间线;③ 使用Allocation sampling按函数查看内存分配。持续增长的堆大小是内存泄漏的典型标志。
闭包会持有其外部函数作用域中的变量引用。如果一个闭包被长期持有(如作为事件回调、存储在全局数组中),而闭包又引用了一个大型数据结构,即使原始函数已执行完毕,该大型数据也无法被GC回收。例如:一个只使用了大对象中某个小属性的闭包,却持有了整个大对象的引用,导致大对象无法释放。
① 使用setTimeout替代setInterval,在回调中递归调用并检查条件;② 在组件销毁/页面卸载时使用clearInterval/clearTimeout清理;③ 在React中使用useEffect的清理函数;④ 在Vue中使用onUnmounted或beforeUnmount生命周期;⑤ 避免在定时器回调中持有DOM引用或闭包大对象;⑥ 使用WeakRef(如果环境支持)来持有可被GC的引用。
本工具通过创建真实的JavaScript内存分配来模拟泄漏:① 使用performance.memory API(Chrome)读取真实堆大小;② 每种泄漏类型以不同方式分配并持有内存(如ArrayBuffer、大型字符串、闭包引用、Map条目等);③ 通过Canvas实时绘制堆增长曲线;④ 所有泄漏数据存储在全局注册表中防止GC回收;⑤ 支持随时清理单个或全部泄漏,观察内存释放效果。在非Chrome浏览器中会使用估算值。
垃圾回收是自动内存管理机制,用于回收不再被引用的内存。现代JavaScript引擎(V8、SpiderMonkey)主要使用标记-清除(Mark-and-Sweep)算法,辅以分代回收策略:新生代使用Scavenge算法(空间换时间),老生代使用Mark-Sweep和Mark-Compact。从根对象(全局对象、栈变量)出发,标记所有可达对象,未被标记的即为垃圾。ES6引入的WeakMap和WeakSet允许创建不阻止GC的弱引用。