js垃圾回收新生代和老生代以及堆栈内存详细

2024-04-01 15:04

本文主要是介绍js垃圾回收新生代和老生代以及堆栈内存详细,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

js 堆栈内存、新生代和老生代、垃圾回收详聊

要想了解JS内存管理就必须明白存这些js数据的内存又分为:栈内存和堆内存

一、 栈|堆内存(Stack|Heap)

  1. 栈(Stack)内存
    原始值:Number、String、Boolean、Null、Undefined、Symbol和BigInt
    栈内存主要存储原始值数据类型
  2. 堆(Heap)内存
    引用值:Object( Object、Array和Function等)
    堆内存主要存储引用值数据类型
     栈|堆内存

案例1

let n = 1;
let b = true;
let s = "string";
let pObj = {name:'dupha',age:18,address:[{"code": "11","name": "北京市","children": [{"code": "1101","name": "市辖区"}]}]};
let pArr = [1,2,3,4,5];

栈|堆内存案例

案例2

//声明 + 第一次赋值
let person= {name:'dupha',age:18,address:[{"code": "11","name": "北京市","children": [{"code": "1101","name": "市辖区"}]}]};   
//第二次赋值
person = {name:'soeng',age:20,address:[{"code": "11","name": "北京市","children": [{"code": "1101","name": "市辖区"}]}]};  

在这里插入图片描述

第一次赋值第二次赋值

下方算法以谷歌chrome浏览器的V8引擎来讲解

二、垃圾回收常用方法

  1. 引用计数法reference counting
    跟踪对象被引用的次数,如果引用次数是 0,那么该对象不再用到,GC时会将其对象清除

如图:

在这里插入图片描述在这里插入图片描述

引用计数存在问题:循环引用的话,对象内存就无法释放

  1. 标记清除法
    从根节点开始,对其进行深度优先遍历,能够达到的标记活跃对象,不能达到的对象标记死对象。

标记清除法
可以看出,碎片化,后续又多了标记整理法(顾名思义就是标记后,再进行碎片化压缩(整理),提高内存的利用率)
类似于硬盘碎片整理
硬盘碎片整理

三、新生代和老生代

 新生代和老生代

  1. 新生代和老生代内存分配
    众所周知,计算机操作系统分为 32位 和 64位
    新生代和老生代也会给予操作系统的不同位数来进行内存分配
    32位 新生代空间: 32MB (to space 和 from space分别16MB),老生代位700MB
    64位 新生代空间: 64MB (to space 和 from space分别32MB),老生代位1400MB
    node中,可以修改最大内存node --max-old-space-size=4096
	//在查看浏览器内存信息window.performance

查看浏览器内存信息

  1. 新生代算法
    新生代算法

scavenger算法:
算法执行周期如下:
第一步:js变量分配内存先在from space上,如果from space满了,执行下一步
第二步:从from space上遍历出活跃对象,判断对象是否已经经过一次周期,
是:判断to space是否超过25%,超过将放入老生代,没超过保持不动
否:将其移至to space
第三步:清空from-Space
第四步:调换to spacefrom space空间
一直循环执行该周期
scavenger算法

  1. 老生代算法
    老生代

标记-清除-压缩(Mark-Sweep-Compaction)算法:

  1. 标记阶段(Mark Phase)
  • 起始点:从一组根对象(如全局对象)开始。
  • 递归访问:递归地访问所有从根对象可达的对象,并将它们标记为“活动”或“可达”。
  • 避免重复访问:使用某种数据结构(如位图或颜色标记)来跟踪已访问过的对象,避免重复访问。
  1. 清除阶段(Sweep Phase)
  • 遍历堆内存:在标记阶段完成后,遍历整个老生代的堆内存。
  • 释放未标记对象:释放所有在标记阶段中未被标记为可达的对象所占用的内存。
  1. 压缩阶段(Compaction Phase)
  • 移动对象:将存活的对象(即标记阶段中标记为可达的对象)移动到堆内存的一端,使它们紧密排列。
  • 更新引用:由于对象在内存中移动了位置,因此需要更新所有指向这些对象的引用,以确保它们指向新的位置。
  • 减少碎片:通过压缩操作,可以消除由清除操作产生的内存碎片,使堆内存更加连续和可用。

标记-清除-压缩

  1. 其他(有趣可自行查阅)
    V8在扫描和标记上,采用过 广度扫描、全停顿标记、增量标记、三色标记等
    清理回收上,采用并行回收,懒性清理等

四、内存泄露有哪些?

  1. 隐式全局变量
function dupha(){data = "假设一个很大的Array or Object";
}

通过直接调用(window / globalThis),用完不清除会占用资源。
隐式全局变量

  1. 闭包
    闭包:函数嵌套函数
    在闭包中,如果里面引用外部函数的变量,它被持续保留在内存中,其变量也无法被垃圾收集器回收。
const dupha = function () {let BigObject = {text:"这是一个很大的OBJ"};return function (y) {console.log(y + JSON.stringify(BigObject));};
};
let f = dupha();
f(1)

注意: 如果闭包方法用完后,最后将其清空(如:f = null,去除闭包方法引用,下一次垃圾收集将被回收)。
在这里插入图片描述

  1. 用完不移除定时器\事件监听
    创建了一个定时器,如果没有明确地移除它,有可能引起:内存泄漏,无意义的执行或者报错。
function getInfoByKey(id){return new Promise((resolve, reject) => {// 模拟接口异步请求数据setTimeout(() => {resolve(`通过Key:${id}来调用返回一个很大的JSON对象`)}, 1000)})
}
var getData = getInfoByKey;
var id = 0;
setInterval(async function (){const data = await getData(id++);console.log(data);
},5000)

用完不移除定时器一直调用,还存在引用

为啥上传不了大文件

文件过大,超过规定内存或者其他原因,采用文件切片

文件属性描述
File.name文件名称
File.size文件大小(如: 2MB 2*1024*1024)
File.type文件类型
File.lastModified最后修改时间
把大文件按照每个2MB/1MB大小进行切割成小文件上传到服务器上。

如有不理解或者不准确的欢迎评论/私聊~

这篇关于js垃圾回收新生代和老生代以及堆栈内存详细的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/867458

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

Python与MySQL实现数据库实时同步的详细步骤

《Python与MySQL实现数据库实时同步的详细步骤》在日常开发中,数据同步是一项常见的需求,本篇文章将使用Python和MySQL来实现数据库实时同步,我们将围绕数据变更捕获、数据处理和数据写入这... 目录前言摘要概述:数据同步方案1. 基本思路2. mysql Binlog 简介实现步骤与代码示例1

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

Java中HashMap的用法详细介绍

《Java中HashMap的用法详细介绍》JavaHashMap是一种高效的数据结构,用于存储键值对,它是基于哈希表实现的,提供快速的插入、删除和查找操作,:本文主要介绍Java中HashMap... 目录一.HashMap1.基本概念2.底层数据结构:3.HashCode和equals方法为什么重写Has

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变

Java使用正则提取字符串中的内容的详细步骤

《Java使用正则提取字符串中的内容的详细步骤》:本文主要介绍Java中使用正则表达式提取字符串内容的方法,通过Pattern和Matcher类实现,涵盖编译正则、查找匹配、分组捕获、数字与邮箱提... 目录1. 基础流程2. 关键方法说明3. 常见场景示例场景1:提取所有数字场景2:提取邮箱地址4. 高级