v8引擎垃圾回收
V8引擎垃圾回收机制
v8引擎负责JavaScript的执行。V8引擎具有内置的垃圾回收机制,用于自动管理内存分配和释放
堆与栈
栈空间
栈空间是小而连续的内存空间,主要用于存储局部变量和函数调用的相关信息,同时栈结构是“先进后出”的策略
栈空间的最大的特点是空间连续,所以在栈中每个元素的地址都是固定的,因此栈空间的查找效率非常高,但是通常在内存中,很难分配到一块很大的连续空间,因此,V8 对栈空间的大小做了限制,如果函数调用层过深,那么 V8 就有可能抛出栈溢出的错误
- 分配和释放速度快:栈上的资源分配和销毁只需要移动指针,因此速度非常快。
- 固定大小:栈的空间是有限的,一旦函数调用层次过多或数据过大,就会导致栈溢出。
- 遵循LIFO原则:后进先出,即最后进入栈的元素会被最先弹出。
堆空间
堆空间是一种树形的存储结构,用来存储对象类型的离散的数据
- 动态分配:堆上的内存空间是动态分配的,可以根据需要分配不同大小的内存块。
- 灵活性高:堆可以存储各种类型的数据,包括对象、数组等复杂数据结构。
- 管理复杂:由于堆的空间是动态分配的,管理起来相对复杂,容易出现内存泄漏等问题
回收策略
1》标记清除
这种算法在 JS 引擎中是最常用的(大部分浏览器都是V8引擎,使用的是标记清除)
大致过程:
首先标记内存中所有的变量(假设所有的都是垃圾,都标记为0);
然后将在上下文中的变量以及被上下文引用的变量的标记清除;
在此之后(离开环境时不再当前环境定义的变量被标记清除)的再被加上标记的变量就是待删除了
优点:
实现比较简单,打标记也无非打与不打两种情况,这使得一位二进制位(0和1)就可以为其标记,非常简单
缺点:
标记清除算法有一个很大的缺点,就是在清除之后,剩余的对象内存位置是不变的,也会导致空闲内存空间是不连续的,出现了 内存碎),并且由于剩余空闲内存不是一整块,它是由不同大小内存组成的内存列表,这就牵扯出了内存分配的问题
标记整理算法:在标记结束后,将活着的对象向内存的一端移动(将不需要清理的对象往内存一端移动),最后清理掉边界的内存
2》引用计数
大致过程:
声明变量并赋值的时候引用次数为1
当同一个值被赋值给另一个比那辆,引用书加1
如果对该值引用的变量被其他值覆盖了,引用书减1
如果引用次数为0时就可以被回收了
优点:
引用计数算法的优点我们对比标记清除来看就会清晰很多,首先引用计数在引用值为 0 时,也就是在变成垃圾的那一刻就会被回收,所以它可以立即回收垃圾
缺点:
首先它需要一个计数器,而此计数器需要占很大的位置,因为我们也不知道被引用数量的上限
其次,循环引用问题;对象A有一个指针指向对象B,而对象B也引用了对象A
对象A、B的引用次数都是2,在函数执行后,其实引用次数仍然时2;但是它们其实都不在作用域中了,属于可以回收的垃圾,但是内存并没有被释放
function circleRef() {let A = new Object()let B = new Object()A.a = BB.b = A}circleRef()
想要释放必须在最后去掉引用关系
A=null
B=null
IE8及以前是使用的引用清除
V8引擎内存空间划分
**1》新生代(new space)**:用于存储新创建的对象。分为两部分,分别是使用去和空闲区
**2》老生代(old space)**:存储生存时间较长的对象。这些对象在新生代中存活一段时间后,会被移动到老生代。老生代内存区域相对较大,因为存储的是长期存活的对象,所以垃圾回收的频率相对较低。老生代内存区又分为老生代指针区和老生代数据区,前者包含大多数可能存在指向其他对象的指针的对象,后者只保存原始数据对象,这些对象没有指向其他对象的指针
**3》大对象区(Large Object Space)**:存放体积超过其他区域大小限制的大对象,这些对象由于体积较大,不会被频繁移动,因此放在单独的区域以避免影响其他对象的垃圾回收
**4》代码区(Code Space)**:存放JavaScript代码,这是唯一拥有执行权限的内存区域
**5》Map区(Map Space)**:用于存放Cell和Map,每个区域都是存放相同大小的元素,结构简单
6》Cell Space和Property Cell Space:用于存储固定大小的Cell对象和与JavaScript对象属性相关的PropertyCell对象,优化属性访问性能
V8引擎的垃圾回收策略
V8 设置了两个垃圾回收器,主垃圾回收器和副垃圾回收器;主垃圾回收器负责收集老生代中的垃圾数据,回收频率较低;副垃圾回收器负责收集新生代中的垃圾数据,回收相比更加频繁
可访问性分析法
V8引擎中采用了这种方法来判断是一个对象是否活跃,具体过程为:将一个称为GC Roots的对象(在浏览器环境中,GC Roots 可以包括:全局的 window 对象、所有原生DOM节点集合等等)作为所有初始存活的对象集合,从这个对象出发,进行遍历,遍历到的就认为是可访问的,为活动对象,需要保留;如果没有遍历到的对象,就是不可访问的,这些就是非活动对象,可能就会被垃圾回收。
新生代
新生代:主要用于存放存活时间较短的对象。使用scavenge算法进行回收
新生代回收过程:
scavenge算法主要使用了一种复制式的方法cheney算法(复制式的方法)来实现;
新生代空间被平等划分为两部分,from space 和to space; 当from space填满之后会进行一次垃圾回收,非存货对象被回收,存活的对象被复制到 to space,from space被清空,from space和to space进行了一次交换
scavenge算法是一种典型的牺牲空间换取时间的算法
新生代垃圾回收采用了并行机制。在新生代垃圾回收的过程中,副垃圾回收器使用并行机制,在整理排序阶段,即活动对象从from-space复制到to-space的时候,启用多个辅助线程并行进行整理。这种并行处理的方式意味着多个线程同时参与垃圾回收的过程,以提高效率。由于多个线程可能竞争同一个新生代的堆内存资源,可能会出现某个活动对象被多个线程进行复制操作的情况。为了解决这个问题,V8在第一个线程对活动对象进行复制完成后,必须去维护复制这个活动对象后的指针转发地址,以便于其他协助线程可以找到该活动对象后可以判断该活动对象是否已被复制。这种机制确保了新生代垃圾回收的正确性和效率
对象晋升(新生代变成老生代)
当一个对象在经过多次复制之后依旧存活,那么它会被认为是一个生命周期较长的对象,在下一次进行垃圾回收时,该对象会被直接转移到老生代中
晋升的条件:
- 对象是否经历过一次
Scavenge算法 - 内存占比是否超过
To空间的25%(避免内存使用过高影响后续的对象分配)
满足其中任意一个就会晋升
老生代
老生代采用Mark-Sweep(标记清除)和Mark-Compact(标记整理)`来进行管理
老生代回收过程:
- 标记;递归遍历一组根元素,遍历能达到的元素是活动对象,达不到的是非活动对象 (Mark-Sweep)
- 清除;老生代垃圾回收器直接将非活动对象(数据、垃圾)清理掉 (Mark-Sweep)
- 整理;(Mark-Compact)
以下几种情况都可以作为根节点:
- 全局对象
- 本地函数的局部变量和参数
- 当前嵌套调用链上的其他函数的变量和参数
Mark-Sweep算法存在一个问题,就是在经历过一次标记清除后,内存空间可能会出现不连续的状态,因为我们所清理的对象的内存地址可能不是连续的,所以就会出现内存碎片的问题,导致后面如果需要分配一个大对象而空闲内存不足以分配,就会提前触发垃圾回收;所以通过Mark-Compact(标记整理)解决内存碎片的问题
一般 10 次Mark-Sweep会伴随一次Mark-Compact
策略优化
最开始的垃圾回收机制有两个大的缺点
- 垃圾回收器在主线程上执行,执行垃圾回收期间会阻塞js执行
- 一次执行一个完整的垃圾回收流程,阻塞时间还是连续的
对此V8做出了许多优化:
一般来说,老生代会保存大量存活的对象,如果在标记阶段将整个堆内存遍历一遍,那么势必会造成严重的卡顿。
因此,为了减少垃圾回收带来的停顿时间,V8引擎又引入了增量标记 的概念,即将原本需要一次性遍历堆内存的操作改为增量标记的方式,先标记堆内存中的一部分对象,然后暂停,将执行权重新交给JS主线程,待主线程任务执行完毕后再从原来暂停标记的地方继续标记,直到标记完整个堆内存。只有在浏览器的空闲时间才会执行对应的任务,否则延迟执行,尽可能少地影响主线程的任务,避免应用卡顿,提升应用性能。
得益于增量标记的好处,V8引擎后续继续引入了延迟清理 和 增量式整理,让清理和整理的过程也变成增量式的。同时为了充分利用多核CPU的性能,也将引入并行标记和并行清理,进一步地减少垃圾回收对主线程的影响,为应用提升更多的性能
- 增量标记:V8使用增量标记,即不是一次性遍历整个堆,而是分批次进行,使得每次正常执行之间的停顿非常短暂;即将原本需要一次性遍历堆内存的操作改为增量标记的方式,先标记堆内存中的一部分对象,然后暂停,将执行权重新交给JS主线程,待主线程任务执行完毕后再从原来暂停标记的地方继续标记,直到标记完整个堆内存
- 延迟清理:在浏览器的空闲时间执行垃圾回收任务
- 增量整理:一次整理一部分
- 并发标记:允许垃圾回收的标记阶段与JavaScript代码执行并行进行,减少了主线程的暂停时间
- 并行处理:多个辅助线程并行进行整理,提高了垃圾回收的效率
相关文章:
v8引擎垃圾回收
V8引擎垃圾回收机制 v8引擎负责JavaScript的执行。V8引擎具有内置的垃圾回收机制,用于自动管理内存分配和释放 堆与栈 栈空间 栈空间是小而连续的内存空间,主要用于存储局部变量和函数调用的相关信息,同时栈结构是“先进后出”的策略 栈…...
H5st5.0.0协议分析
签名核心:设备注册 5 8 9段签名校验 其中第八段主要收集了一些指纹信息 需要 对应一致 注册核心加密: fp localTk fp - 16位字符串 localTk - 92位字符串 tls指纹检测 py、js纯算皆可调用 注意:仅供学习交流,与作者无关&am…...
明达助力构建智能变电站新体系
背景概述 随着智能电网技术的飞速进步与电力需求的持续增长,变电站作为电力传输网络的核心节点,其运维效率及安全性能对电网的整体稳定运行起着决定性作用。传统的人工巡检和维护手段已难以匹配现代电网对高效性、实时性及智能化管理的迫切需求。因此&a…...
Flink优化----FlinkSQL 调优
目录 FlinkSQL 调优 1 设置空闲状态保留时间 2 开启 MiniBatch 3 开启 LocalGlobal 3.1 原理概述 3.2 提交案例:统计每天每个 mid 出现次数 3.3 提交案例:开启 miniBatch 和 LocalGlobal 4 开启 Split Distinct 4.1 原理概述 4.2 提交案例&…...
机器学习(二)-简单线性回归
文章目录 1. 简单线性回归理论2. python通过简单线性回归预测房价2.1 预测数据2.2导入标准库2.3 导入数据2.4 划分数据集2.5 导入线性回归模块2.6 对测试集进行预测2.7 计算均方误差 J2.8 计算参数 w0、w12.9 可视化训练集拟合结果2.10 可视化测试集拟合结果2.11 保存模型2.12 …...
01.01、判定字符是否唯一
01.01、[简单] 判定字符是否唯一 1、题目描述 实现一个算法,确定一个字符串 s 的所有字符是否全都不同。 在这一题中,我们的任务是判断一个字符串 s 中的所有字符是否全都不同。我们将讨论两种不同的方法来解决这个问题,并详细解释每种方法…...
第五届“传智杯”全国大学生计算机大赛(练习赛)水题题解
目录 复读 题目描述 输入格式 输出格式 输入输出 说明/提示 源代码 时钟 题目描述 输入格式 输出格式 输入输出 说明/提示 源代码 平等的交易 题目描述 输入格式 输出格式 输入输出 说明/提示 源代码 清洁工 题目描述 输入格式 输出格式 输入输出…...
iOS 苹果开发者账号: 查看和添加设备UUID 及设备数量
参考链接:苹果开发者账号下添加新设备UUID - 简书 如果要添加新设备到 Profiles 证书里: 1.登录开发者中心 Sign In - Apple 2.找到证书设置: Certificate,Identifiers&Profiles > Profiles > 选择对应证书 edit &g…...
推进数字园区建设-成都国际数字影像产业园
在当今数字化浪潮的席卷下,数字园区建设已成为推动区域经济发展、提升产业竞争力的关键举措。成都国际数字影像产业园作为数字产业领域的重要项目,以其独特的发展模式和创新实践,在推进数字园区建设方面取得了显著成效,为数字产业…...
oracle linux8.10+ oracle 23ai安装
介质准备: 数据库23ai https://edelivery.oracle.com 上述网站下载基础版本,本次未使用。 本次是安装了带补丁的版本: Database Release Update 23.6.0.24.10 GoldImage表示带补丁用于直接安装的软件包 查找888.1对应Primary Note for …...
PH热榜 | 2024-12-25
1. Assistive24 标语:为残障人士提供的免费辅助技术 介绍:Assistive24 是一款免费的 Chrome 浏览器扩展程序,可以帮助患有注意力缺陷多动障碍 (ADHD)、阅读障碍 (dyslexia) 和低视力等障碍的用户更方便地浏览网页。它提供语音导航、自定义…...
OpenCV相机标定与3D重建(36)计算两幅图像之间基本矩阵(Fundamental Matrix)的函数findFundamentalMat()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 从两幅图像中的对应点计算基本矩阵。 cv::findFundamentalMat 是 OpenCV 中用于计算两幅图像之间基本矩阵(Fundamental Matrix&#…...
ZLG嵌入式笔记 | 电源设计避坑(上)
产品上量后,通常都会有降成需求。多年来,接触过不少产品降成案例,在电源上下刀过猛,引发了产品偶发性问题,带来了很不好的负面影响。本文将对这些案例进行总结,提供电源设计参考,确保产品降成不…...
.NET能做什么?全面解析.NET的应用领域
.NET 是由微软开发的一个开源、跨平台的开发框架。它不仅支持构建各种应用程序,还能运行在不同的操作系统上,包括 Windows、Linux 和 macOS。自从 .NET Core 的推出,.NET 成为了一个现代化的开发平台,能够满足企业和开发者日益多样…...
初始JavaEE篇 —— 网络原理---传输层协议:深入理解UDP/TCP
找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程程(ಥ_ಥ)-CSDN博客 所属专栏:JavaEE 目录 UDP协议 参数解析: 校验和的计算 TCP协议 参数解析: 确认应答机制 超时重传 连接管理 三次握…...
企业如何搭建安全的跨网文件安全交换管理系统
在数字化转型的浪潮中,企业对数据的安全性和流动性提出了前所未有的高要求。特别是在网络隔离的情况下,如何实现跨网的安全、高效的文件交换成为了众多企业迫切需要解决的问题。 这不仅是技术上的挑战,还涉及到企业内部管理流程的优化和安全策…...
2023 年 12 月青少年软编等考 C 语言四级真题解析
目录 T1. 移动路线T2. 公共子序列T3. 田忌赛马T4. 宠物小精灵之收服 T1. 移动路线 此题为 2021 年 12 月四级第一题原题,见 2021 年 12 月青少年软编等考 C 语言四级真题解析中的 T1。 T2. 公共子序列 此题为 2022 年 3 月四级第四题原题,见 2022 年 …...
GDPU Vue前端框架开发 期末赛道出勇士篇(更新ing)
记住,年底陪你跨年的不会仅是方便面跟你的闺蜜,还有孑的笔记。 选择题 1.下列选项用于设置Vue.js页面视图的元素是()。 A. Template B. script C. style D. title 2.下列选项中能够定义Vuejs根实例对象的元素是(&…...
老旧小区用电安全保护装置#限流式防火保护器参数介绍#
摘要 随着居民住宅区用电负荷的增加,用电安全问题日益突出,火灾隐患频繁发生。防火限流式保护器作为一种新型电气安全设备,能够有效预防因电气故障引发的火灾事故。本文介绍了防火限流式保护器的工作原理、技术特点及其在居民住宅区用电系统…...
7.C语言 宏(Macro) 宏定义,宏函数
目录 宏定义 宏函数 1.注释事项 2.注意事项 宏(Macro)用法 常量定义 简单函数实现 类型检查 条件编译 宏函数计算参数个数 宏定义进行类型转换 宏定义进行位操作 宏定义进行断言 总结 宏定义 #include "stdio.h" #include "string.h" #incl…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
手动给中文分词和 直接用神经网络RNN做有什么区别
手动分词和基于神经网络(如 RNN)的自动分词在原理、实现方式和效果上有显著差异,以下是核心对比: 1. 实现原理对比 对比维度手动分词(规则 / 词典驱动)神经网络 RNN 分词(数据驱动)…...
Linux中INADDR_ANY详解
在Linux网络编程中,INADDR_ANY 是一个特殊的IPv4地址常量(定义在 <netinet/in.h> 头文件中),用于表示绑定到所有可用网络接口的地址。它是服务器程序中的常见用法,允许套接字监听所有本地IP地址上的连接请求。 关…...
