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

相关文章

使用Redis快速实现共享Session登录的详细步骤

《使用Redis快速实现共享Session登录的详细步骤》在Web开发中,Session通常用于存储用户的会话信息,允许用户在多个页面之间保持登录状态,Redis是一个开源的高性能键值数据库,广泛用于... 目录前言实现原理:步骤:使用Redis实现共享Session登录1. 引入Redis依赖2. 配置R

使用Python的requests库调用API接口的详细步骤

《使用Python的requests库调用API接口的详细步骤》使用Python的requests库调用API接口是开发中最常用的方式之一,它简化了HTTP请求的处理流程,以下是详细步骤和实战示例,涵... 目录一、准备工作:安装 requests 库二、基本调用流程(以 RESTful API 为例)1.

Python pandas库自学超详细教程

《Pythonpandas库自学超详细教程》文章介绍了Pandas库的基本功能、安装方法及核心操作,涵盖数据导入(CSV/Excel等)、数据结构(Series、DataFrame)、数据清洗、转换... 目录一、什么是Pandas库(1)、Pandas 应用(2)、Pandas 功能(3)、数据结构二、安

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

最新Spring Security的基于内存用户认证方式

《最新SpringSecurity的基于内存用户认证方式》本文讲解SpringSecurity内存认证配置,适用于开发、测试等场景,通过代码创建用户及权限管理,支持密码加密,虽简单但不持久化,生产环... 目录1. 前言2. 因何选择内存认证?3. 基础配置实战❶ 创建Spring Security配置文件

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

2025版mysql8.0.41 winx64 手动安装详细教程

《2025版mysql8.0.41winx64手动安装详细教程》本文指导Windows系统下MySQL安装配置,包含解压、设置环境变量、my.ini配置、初始化密码获取、服务安装与手动启动等步骤,... 目录一、下载安装包二、配置环境变量三、安装配置四、启动 mysql 服务,修改密码一、下载安装包安装地

在macOS上安装jenv管理JDK版本的详细步骤

《在macOS上安装jenv管理JDK版本的详细步骤》jEnv是一个命令行工具,正如它的官网所宣称的那样,它是来让你忘记怎么配置JAVA_HOME环境变量的神队友,:本文主要介绍在macOS上安装... 目录前言安装 jenv添加 JDK 版本到 jenv切换 JDK 版本总结前言China编程在开发 Java

Spring Boot Actuator应用监控与管理的详细步骤

《SpringBootActuator应用监控与管理的详细步骤》SpringBootActuator是SpringBoot的监控工具,提供健康检查、性能指标、日志管理等核心功能,支持自定义和扩展端... 目录一、 Spring Boot Actuator 概述二、 集成 Spring Boot Actuat