js删除节点的方法(JSfor循环删除指定节点)

内存管理V8内存限制限制大小64位为1.4GB,32位为0.7GB限制原因V8之所以限制了内存的大小,表面上的原因是V8最初是作为浏览器的JavaScript引擎而设计,不太可能遇到大量内存的场景,而深层次的原因则是由于V8的

内存管理

V8 内存限制

限制大小

64 位为 1.4GB,32 位为 0.7GB

限制原因

V8 之所以限制了内存的大小,表面上的原因是 V8 最初是作为浏览器的 JavaScript 引擎而设计,不太可能遇到大量内存的场景,而深层次的原因则是由于 V8 的垃圾回收机制的限制。由于 V8 需要保证 JavaScript 应用逻辑与垃圾回收器所看到的不一样,V8 在执行垃圾回收时会阻塞 JavaScript 应用逻辑,直到垃圾回收结束再重新执行 JavaScript 应用逻辑,这种行为被称为“全停顿”(stop-the-world)。若 V8 的堆内存为 1.5GB,V8 做一次小的垃圾回收需要 50ms 以上,做一次非增量式的垃圾回收甚至要 1 秒以上。这样浏览器将在 1s 内失去对用户的响应,造成假死现象。如果有动画效果的话,动画的展现也将显著受到影响。

V8 垃圾回收策略

  • 采用分代回收的思想
  • 内存分为新生代、老生代
  • 针对新、老生代采用不同算法来提升垃圾回收的效率

新生代的对象为存活时间较短的对象,老生代中的对象为存活时间较长或常驻内存的对象。

V8 新生代、老生代内存大小

V8 引擎的新生代内存大小 32MB(64 位)、16MB(32 位),老生代内存大小为 1400MB(64 位)、700MB( 32 位)。

新生代对象回收实现

  • 回收过程采用复制算法+标记整理
  • 新生代内存区被等分为两个空间
  • 使用空间为 From,空闲空间为 To
  • 标记整理后将活动对象拷贝至 To
  • From 和 To 交换空间完成释放

js删除节点的方法(JSfor循环删除指定节点)

晋升

将新生代对象移到老生代

晋升条件

  • 一轮 GC 还存活的新生代需要晋升
  • 对象从 From 空间复制到 To 空间时,如果 To 空间已经被使用了超过 25%,那么这个对象直接被复制到老生代

老生代对象回收实现

  • 主要采取标记清除、标记整理、增量标记算法
  • 首先使用标记清除完成垃圾空间的回收
  • 采用标记整理进行空间优化
  • 采用增量标记进行效率优化

细节对比

新生代区域,采用复制算法, 因此其每时每刻内部都有空闲空间的存在(为了完成 From 到 To 的对象复制),但是新生代区域空间较小(32M)且被一分为二,所以这种空间上的浪费也是比较微不足道的。

老生代因其空间较大(1.4G),如果同样采用一分为二的做法则对空间大小是比较浪费,且老生代空间较大,存放对对象也较多,如果进行复制算法,则其消耗对时间也会更大。也就是是否使用复制算法来进行垃圾回收,是一个时间 T 关于内存大小的关系,当内存大小较小时,使用复制算法消耗的时间是比较短的,而当内存较大时,采用复制算法对时间对消耗也就更大。

V8 的优化

增量标记

由于全停顿会造成了浏览器一段时间无响应,所以 V8 使用了一种增量标记的方式,将完整的标记拆分成很多部分,每做完一部分就停下来,让 JS 的应用逻辑执行一会,这样垃圾回收与应用逻辑交替完成。经过增量标记的改进后,垃圾回收的最大停顿时间可以减少到原来的 1/6 左右

js删除节点的方法(JSfor循环删除指定节点)

惰性清理

由于标记完成后,所有的对象都已经被标记,不是死对象就是活对象,堆上多少空间格局已经确定。我们可以不必着急释放那些死对象所占用的空间,而延迟清理过程的执行。垃圾回收器可以根据需要逐一清理死对象所占用的内存空间

其他

V8 后续还引入了增量式整理(incremental compaction),以及并行标记和并行清理,通过并行利用多核 CPU 来提升垃圾回收的性能

监控内存

内存问题的外在表现

  • 页面出现延迟加载或经常性暂停: 可能存在频繁当 GC 操作,存在一些代码瞬间吃满了内存。
  • 页面出现持续性的糟糕性能: 程序为了达到最优的运行速度,向内存申请了一片较大的内存空间,但空间大小超过了设备所能提供的大小。
  • 页面使用随着时间延长越来越卡:可能存在内存泄漏。

界定内存问题的标准

  • 内存泄漏:内存使用持续升高
  • 内存膨胀:在多数设备上都存在性能问题
  • 频繁垃圾回收:通过内存变化时序图进行分析

监控内存方式

任务管理器

这里以 Google 浏览器为例,使用 Shift + Esc 唤起 Google 浏览器自带的任务管理器

  • Memory(内存) 列表示原生内存。DOM 节点存储在原生内存中。如果此值正在增大,则说明正在创建 DOM 节点。
  • JavaScript Memory(JavaScript 内存) 列表示 JS 堆。此列包含两个值。您感兴趣的值是实时数字(括号中的数字)。实时数字表示您的页面上的可到达对象正在使用的内存量。如果此数字在增大,要么是正在创建新对象,要么是现有对象正在增长。

模拟内存泄漏

在任务管理器里可以看到 JavaScript 内存持续上升

document.body.innerHTML = `<button id=\"add\">add</button>`;
document.getElementById(\'add\').addEventListener(\'click\', function (e) {
simulateMemoryLeak();
});
let result = [];
function simulateMemoryLeak() {
setInterval(function () {
result.push(new Array(1000000).join(\'x\'));
document.body.innerHTML = result;
}, 100);
}

Timeline 记录内存

这里以 Google 浏览器为例,使用 F12 开启调式,选择 Performance,点击 record(录制),进行页面操作,点击 stop 结束录制之后,开启内存勾选,拖动截图到指定时间段查看发生内存问题时候到页面展示,并定位问题。同时可以查看对应出现红点到执行脚本,定位问题代码。

js删除节点的方法(JSfor循环删除指定节点)

利用浏览器内存模块,查找分离 dom

这里以 Google 浏览器为例,在页面上进行相关操作后,使用 F12 开启调式,选择 Memory,点击 Take snapshot(拍照),在快照中查找 Detached HTMLElement,回到代码中查找对应的分离 dom 存在的代码,在相关操作代码之后,对分离 dom 进行释放,防止内存泄漏。

只有页面的 DOM 树或 JavaScript 代码不再引用 DOM 节点时,DOM 节点才会被作为垃圾进行回收。如果某个节点已从 DOM 树移除,但某些 JavaScript 仍然引用它,我们称此节点为“已分离”。已分离的 DOM 节点是内存泄漏的常见原因。

模拟已分离 DOM 节点

document.body.innerHTML = `<button id=\"add\">add</button>`;
document.getElementById(\'add\').addEventListener(\'click\', function (e) {
create();
});
let detachedTree;
function create() {
let ul = document.createElement(\'ul\');
for (let i = 0; i < 10; i++) {
let li = document.createElement(\'li\');
ul.appendChild(li);
}
detachedTree = ul;
}

js删除节点的方法(JSfor循环删除指定节点)

如何确定频繁对垃圾回收

  • GC 工作时,程序是暂停的,频繁/过长的 GC 会导致程序假死,用户会感知到卡顿。
  • 查看 Timeline 中是否存在内存走向在短时间内频繁上升下降的区域。浏览器任务管理器是否频繁的增加减少。

代码优化

jsPerf(JavaScript 性能测试)

基于 Benchmark.js

慎用全局变量

  • 全局变量定义在全局执行的上下文,是所有作用域链的顶端
  • 全局执行上下文一直存在于上下文执行栈,直到程序退出
  • 如果某个局部作用域出现了同名变量则会屏蔽或者污染全局作用域
  • 全局变量的执行速度,访问速度要低于局部变量,因此对于一些需要经常访问的全局变量可以在局部作用域中进行缓存

js删除节点的方法(JSfor循环删除指定节点)

上图可以看出,test2 的性能要比 test1 的性能要好,从而得知,全局变量的执行速度,访问速度要低于局部变量

避免全局查找

js删除节点的方法(JSfor循环删除指定节点)

上图可以看出,test2 的性能要比 test1 的性能要好,从而得知,缓存全局变量后使用可以提升性能

通过原型对象添加附加方法提高性能

js删除节点的方法(JSfor循环删除指定节点)

上图可以看出,test2 的性能要比 test1 的性能要好,从而得知,通过原型对象添加方法与直接在对象上添加成员方法相比,原型对象上的属性访问速度较快。

避开闭包陷阱

闭包特点

  • 外部具有指向内部的引用
  • 在“外”部作用域访问“内”部作用域的数据

function foo() {
let name = \'heath\';
function fn() {
console.log(name);
}
return fn;
}
let a = foo();
a();

闭包使用不当很容易出现内存泄漏

function f5() {
// el 引用了全局变量document,假设btn节点被删除后,因为这里被引用着,所以这里不会被垃圾回收,导致内存泄漏
let el = document.getElementById(\'btn\');
el.onclick = function (e) {
console.log(e.id);
};
}
f5();
function f6() {
// el 引用了全局变量document,假设btn节点被删除后,因为这里被引用着,所以这里不会被垃圾回收,导致内存泄漏
let el = document.getElementById(\'btn\');
el.onclick = function (e) {
console.log(e.id);
};
el = null; // 我们这里手动将el内存释放,从而当btn节点被删除后,可以被垃圾回收
}
f6();

避免属性访问方法使用

JavaScript 中的面向对象

  • JS 不需属性的访问方法,所有属性都是外部可见的
  • 使用属性访问方法只会增加一层重定义,没有访问的控制力

js删除节点的方法(JSfor循环删除指定节点)

上图可以看出,test2 的性能要比 test1 的性能要好不少,从而得知,直接访问属性,会比通过方法访问属性速度来的快。

遍历速度

js删除节点的方法(JSfor循环删除指定节点)

上图可以看出,loop 遍历速度 forEach > 优化 for > for of > for > for in

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请发送邮件至 55@qq.com 举报,一经查实,本站将立刻删除。转转请注明出处:https://www.szhjjp.com/n/18153.html

(0)
nan
上一篇 2021-08-28
下一篇 2021-08-28

相关推荐

  • 数据库设计对SQL拼接有哪些影响

    数据库设计对SQL拼接有以下几种影响:表设计:数据库中的表设计会直接影响到SQL拼接的复杂度和效率。如果表设计不合理,例如表的字段过多或者字段冗余,会导致SQL拼接变得复杂,同时也会增加SQL查询的时间和资源消耗。索引设计:数据库中的索引设计会直接影响到SQL查询的性能。如果索引设计不合理,会导致SQL拼接的查询时间变长,同时也会增加数据库的负载。视图设计:数据库中的视图设计也会对SQL拼接有影响

    2024-04-29
    0
  • Torch中如何进行超参数搜索

    在Torch中进行超参数搜索通常可以使用GridSearch或者RandomSearch方法。以下是一个简单的示例代码,使用GridSearch方法来搜索超参数的最佳组合:from torch import nnfrom torch.optim import Adamfrom sklearn.model_selection import ParameterGrid# 定义模型class S

    2024-03-08
    0
  • 如何判断设计的好坏(怎么判断设计师好坏)

    如何判断设计的好坏,怎么判断设计师好坏 内容导航: 评价设计好坏的终极标准到底有没有 设计的8个原则还有怎么判断一个设计的好坏 怎么判断一个标志设计的好坏 如何判断一个设计作品的好…

    2022-08-19
    0
  • sqlserver数据加密的方法是什么

    SQL Server 数据加密包括对数据进行加密和解密的过程。以下是 SQL Server 中常见的数据加密方法:数据列级加密:可以使用 T-SQL 函数如 ENCRYPTBYPASSPHRASE() 和 DECRYPTBYPASSPHRASE() 来加密和解密数据列。透明数据加密(TDE):TDE 是 SQL Server 提供的一种全盘加密技术,可以加密整个数据库,包括数据文件和日志文件。使用

    2024-03-23
    0
  • 高防服务器租用需要注意什么事项

    租用高防服务器是一项重要的决定,因此需要注意以下事项:需要根据自己的业务需求选择合适的高防服务器,包括带宽、防护能力、技术支持等方面的要求。选择信誉良好的服务商,确保服务器的稳定性和安全性。确保高防服务器的防护能力足够强大,能够有效抵御各种网络攻击,如DDoS攻击、SQL注入等。注意高防服务器的价格和费用,选择符合自己预算的服务器服务。确保高防服务器的技术支持团队能够及时响应和处理问题,保障业务的

    2024-04-08
    0
  • mybatis分页查询数据慢如何解决

    Mybatis 分页查询数据慢可能是由于数据量大、查询条件复杂、数据库索引不合理等原因造成的,可以尝试以下几种方法来解决:添加合适的索引:确保查询字段上有合适的索引,可以大大提高查询的效率。分页查询优化:尽量减少查询返回的数据量,可以通过调整分页大小、只查询需要的字段等方式来优化查询。缓存数据:可以使用缓存技术将频繁查询的数据缓存起来,减少数据库访问次数。数据库优化:对数据库进行适当的优化,如调整

    2024-03-25
    0

发表回复

登录后才能评论