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

相关文章

SQL Server中行转列方法详细讲解

《SQLServer中行转列方法详细讲解》SQL行转列、列转行可以帮助我们更方便地处理数据,生成需要的报表和结果集,:本文主要介绍SQLServer中行转列方法的相关资料,需要的朋友可以参考下... 目录前言一、为什么需要行转列二、行转列的基本概念三、使用PIVOT运算符进行行转列1.创建示例数据表并插入数

Python + Streamlit项目部署方案超详细教程(非Docker版)

《Python+Streamlit项目部署方案超详细教程(非Docker版)》Streamlit是一款强大的Python框架,专为机器学习及数据可视化打造,:本文主要介绍Python+St... 目录一、针对 Alibaba Cloud linux/Centos 系统的完整部署方案1. 服务器基础配置(阿里

C# GC回收的方法实现

《C#GC回收的方法实现》本文主要介绍了C#GC回收的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录 一、什么是 GC? 二、GC 管理的是哪部分内存? 三、GC 什么时候触发?️ 四、GC 如何判断一个对象是“垃圾

JAVA SpringBoot集成Jasypt进行加密、解密的详细过程

《JAVASpringBoot集成Jasypt进行加密、解密的详细过程》文章详细介绍了如何在SpringBoot项目中集成Jasypt进行加密和解密,包括Jasypt简介、如何添加依赖、配置加密密钥... 目录Java (SpringBoot) 集成 Jasypt 进行加密、解密 - 详细教程一、Jasyp

Java 操作 MinIO详细步骤

《Java操作MinIO详细步骤》本文详细介绍了如何使用Java操作MinIO,涵盖了从环境准备、核心API详解到实战场景的全过程,文章从基础的桶和对象操作开始,到大文件分片上传、预签名URL生成... 目录Java 操作 MinIO 全指南:从 API 详解到实战场景引言:为什么选择 MinIO?一、环境

Java JAR 启动内存参数配置指南(从基础设置到性能优化)

《JavaJAR启动内存参数配置指南(从基础设置到性能优化)》在启动Java可执行JAR文件时,合理配置JVM内存参数是保障应用稳定性和性能的关键,本文将系统讲解如何通过命令行参数、环境变量等方式... 目录一、核心内存参数详解1.1 堆内存配置1.2 元空间配置(MetASPace)1.3 线程栈配置1.

Redis的安全机制详细介绍及配置方法

《Redis的安全机制详细介绍及配置方法》本文介绍Redis安全机制的配置方法,包括绑定IP地址、设置密码、保护模式、禁用危险命令、防火墙限制、TLS加密、客户端连接限制、最大内存使用和日志审计等,通... 目录1. 绑定 IP 地址2. 设置密码3. 保护模式4. 禁用危险命令5. 通过防火墙限制访问6.

Python操作Excel的实用工具与库openpyxl/pandas的详细指南

《Python操作Excel的实用工具与库openpyxl/pandas的详细指南》在日常数据处理工作中,Excel是最常见的数据文件格式之一,本文将带你了解openpyxl和pandas的核心用法,... 目录一、openpyxl:原生 Excel 文件操作库1. 安装 openpyxl2. 创建 Exc

Python中isinstance()函数原理解释及详细用法示例

《Python中isinstance()函数原理解释及详细用法示例》isinstance()是Python内置的一个非常有用的函数,用于检查一个对象是否属于指定的类型或类型元组中的某一个类型,它是Py... 目录python中isinstance()函数原理解释及详细用法指南一、isinstance()函数

Python的pandas库基础知识超详细教程

《Python的pandas库基础知识超详细教程》Pandas是Python数据处理核心库,提供Series和DataFrame结构,支持CSV/Excel/SQL等数据源导入及清洗、合并、统计等功能... 目录一、配置环境二、序列和数据表2.1 初始化2.2  获取数值2.3 获取索引2.4 索引取内容2