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内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

Java操作PDF文件实现签订电子合同详细教程

《Java操作PDF文件实现签订电子合同详细教程》:本文主要介绍如何在PDF中加入电子签章与电子签名的过程,包括编写Word文件、生成PDF、为PDF格式做表单、为表单赋值、生成文档以及上传到OB... 目录前言:先看效果:1.编写word文件1.2然后生成PDF格式进行保存1.3我这里是将文件保存到本地后

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

使用SpringBoot创建一个RESTful API的详细步骤

《使用SpringBoot创建一个RESTfulAPI的详细步骤》使用Java的SpringBoot创建RESTfulAPI可以满足多种开发场景,它提供了快速开发、易于配置、可扩展、可维护的优点,尤... 目录一、创建 Spring Boot 项目二、创建控制器类(Controller Class)三、运行

springboot整合gateway的详细过程

《springboot整合gateway的详细过程》本文介绍了如何配置和使用SpringCloudGateway构建一个API网关,通过实例代码介绍了springboot整合gateway的过程,需要... 目录1. 添加依赖2. 配置网关路由3. 启用Eureka客户端(可选)4. 创建主应用类5. 自定

最新版IDEA配置 Tomcat的详细过程

《最新版IDEA配置Tomcat的详细过程》本文介绍如何在IDEA中配置Tomcat服务器,并创建Web项目,首先检查Tomcat是否安装完成,然后在IDEA中创建Web项目并添加Web结构,接着,... 目录配置tomcat第一步,先给项目添加Web结构查看端口号配置tomcat    先检查自己的to

使用Nginx来共享文件的详细教程

《使用Nginx来共享文件的详细教程》有时我们想共享电脑上的某些文件,一个比较方便的做法是,开一个HTTP服务,指向文件所在的目录,这次我们用nginx来实现这个需求,本文将通过代码示例一步步教你使用... 在本教程中,我们将向您展示如何使用开源 Web 服务器 Nginx 设置文件共享服务器步骤 0 —

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

SpringBoot集成SOL链的详细过程

《SpringBoot集成SOL链的详细过程》Solanaj是一个用于与Solana区块链交互的Java库,它为Java开发者提供了一套功能丰富的API,使得在Java环境中可以轻松构建与Solana... 目录一、什么是solanaj?二、Pom依赖三、主要类3.1 RpcClient3.2 Public