重学Node系列03-内存管理及GC算法

简介: Node内存控制这是重新阅读《深入浅出NodeJS》的相关笔记,这次阅读发现自己依旧收获很多,而第一次阅读的东西也差不多忘记完了,所以想着这次过一遍脑子,用自己的理解输出一下,方便记忆以及以后回忆...

Node内存控制

这是重新阅读《深入浅出NodeJS》的相关笔记,这次阅读发现自己依旧收获很多,而第一次阅读的东西也差不多忘记完了,所以想着这次过一遍脑子,用自己的理解输出一下,方便记忆以及以后回忆...

基本介绍


说到node对于内存的控制,可能最先想到的就是node是基于V8构建,因此在node中通过JavaScript使用内存时就会发现只能使用部分内存(64位系统约为1.4GB,32位系统约为0.7GB)。在这样的限制下,将会导致node无法直接操作大内存对象,即使你本机的物理内存有32GB也不行,这与我们传统上的认知形成了一定的差别,接下来先解释一下为什么有这样的差别:

注:64位系统约为1.4GB,32位系统约为0.7GB为默认,也可以用户自定义--max-old-space-size--max-new-space-size来调整,不过只能在启动时指定,node无法运行中自动扩充

首先,V8的设计就是在浏览器的应用场景下完成的,这套内存管理机制在浏览器下使用是绰绰有余的,只是在node中使用有些限制,当然,也有其他方式来解决,只是不能让开发者随心所欲地使用大内存了。

其实深层原因是V8的垃圾回收机制的限制,每次垃圾回收都必须让JavaScript线程暂停,如果垃圾回收时间过长会导致应用的性能和响应能力都会直线下降,所以V8当时的考虑直接限制堆内存是一个好的选择;这中停顿叫做“全停顿”,V8为此也还做了许多优化,这个后续章节会讲到

回到这一部分,介绍一个比较常见的命令:我们在node中输入process.memoryUsage(),就可以很方便地查看node内存使用量的相关信息:

简单解释一下其中的含义,详细参考

注:V8中的所有JavaScript对象都是通过堆来进行分配的

  • rss:Resident Set Size,是该进程所占用的总空间量,包含所有C++JavaScript对象和代码
  • heapTotal:已经申请到的堆内存
  • heapUsed:当前使用的堆内存
  • external:指绑定到 V8 管理的 JavaScript 对象的 C++ 对象的内存使用情况
  • arrayBuffers:包含的Buffer对象,该值包含在external

值得注意的是:V8在上述变量中只负责了堆内存的分配,external包含的内存并不是通过V8管理的,所以我们在external中操作的东西可以不受V8的内存限

垃圾回收机制


总的来说,V8的垃圾回收策略是基于分代式垃圾回收机制,分为新生代和老生代。其中新生代的对象为存活时间较短的对象,老生代的对象为存活时间较长的对象,这里先介绍结论,具体原因后续讲到。

新生代


新生代中主要通过Scavenge算法进行垃圾回收,这是典型的空间换时间的算法,会牺牲一半的存储空间,但速度较快,正好与新生代中对象的特点相对应

该算法主要采取复制的方式进行的垃圾回收,如下图所示:

之前提到过这个算法与新生代的特点向符合,解释一下,新生代里面对象的特点就是生命周期较短,所以在下一次复制过程中存活的对象一般来说是比较少的,而这个算法是只复制存活的对象,所以时间效率上有优异的表现,同时这中将存活中的对象直接在另一半内存空间中依次排列,不会产生老生代那种算法的内存碎片问题(后续会讲到)

晋升

其实一开始对象声明的时候,V8也不知道这个对象是否生命周期较短,那它是如何判断从而将对象区分到新生代区域和老生代区域之中的呢?

答案就是本小节的标题,“晋升”:当一个对象经过多次复制依然存活时或者该对象To空间的占用比超出限制(一般25%),它将会被执行晋升操作,放入到老生代区域之中(注意:只要这两个条件满足一个,就会执行晋升操作,这是个“或”条件)

老生代


结合老生代的特点,V8在老生代中主要采取了Mark-SweepMark-Compact相结合的方式进行垃圾回收,就是标记清除和标记整理

标记清除

  • 标记阶段:标记活着的对象
  • 清除阶段:清除没被标记的对象

老生代的特点就是存活时间长,即失活对象的占比一般来说是比较小的,所以这里是清除死亡的对象是合理的。而不是与新生代算法一致,复制活着的对象,并且由于老生代对象占用内存较大,所以分出一半空间来说也是不合理的

标记整理:在标记清除的基础上提出来的,在对象标记为死亡后,整理的过程中,会将活着的对象往一边移动,移动完成后,直接清理掉边界外的内存。

注意:V8并不是直接采取标记整理的方式来管理老生代,而是通过标记清除和标记整理相结合的方式进行处理,因为它们在处理效率上有较大差别,毕竟标记清理多做了移动的操作。

回收算法 Mark-Sweep Mark-compact Scavenge
速度 中等 最慢 最快
空间开销 少(有碎片) 少(无碎片) 双倍空间(无碎片)
是否移动对象

这种分层级处理方式在计算机中非常常见,最容易想到的就是比如速度上寄存器 > 内存 > 外存,而价格上寄存器 < 内存 < 外存,所以计算机的存储结构就采取了三级分层策略来平衡速度与价格;就像V8中于内存的处理是在时间和空间以及内存碎片等维度上进行平衡的。

所以在取舍中,V8主要使用标记清除算法,在空间不足以对新生代晋升过来的对象进行分配的时候才使用标记整理算法(如下图)

全停顿问题


上述中的三种基本垃圾回收算法都需要将应用逻辑(JavaScript执行线程)暂停下来,待执行完垃圾回收后再恢复执行应用逻辑,这样做是为了避免JavaScript应用逻辑与垃圾回收器看到的不一致的情况。这种行为就是文章前面提到的“全停顿”;

而且老生代通常配置得较大,且活动对象较多,全堆垃圾回收得标记、清理、整理等动作造成得停顿就会比较可怕,需要优化:

这就是“增量标记”出现的原因,具体过程就是将原本要以口气停顿完成的动作改为增量标记的方式,也就是拆分为寻多个小“步进”,每做完一个“步进”就让JavaScript执行一小会儿

同时还有延迟清理与增量式整理,让清理和整理的动作也变成增量式等一系列优化操作,这里不深入研究。

内存泄漏


通常造成内存泄漏的原因有这些:

  • 缓存:把内存作缓存,却没有过期策略清除,导致越来越多
  • 队列消费不及时:生产速度远远大于消费速度,队列长度没做限制的话就会无限变大,导致内存泄漏
  • 作用域未释放

内存监控及内存泄漏解决方案


TODO,功力不够,后续来补,主要是还没实践经验,这里先挖个坑。。。



目录
相关文章
|
14天前
|
运维 监控 JavaScript
内网网管软件中基于 Node.js 的深度优先搜索算法剖析
内网网管软件在企业网络中不可或缺,涵盖设备管理、流量监控和安全防护。本文基于Node.js实现深度优先搜索(DFS)算法,解析其在网络拓扑遍历中的应用。通过DFS,可高效获取内网设备连接关系,助力故障排查与网络规划。代码示例展示了图结构的构建及DFS的具体实现,为内网管理提供技术支持。
35 11
|
11天前
|
监控 网络协议 算法
基于问题“如何监控局域网内的电脑”——Node.js 的 ARP 扫描算法实现局域网内计算机监控的技术探究
在网络管理与安全领域,监控局域网内计算机至关重要。本文探讨基于Node.js的ARP扫描算法,通过获取IP和MAC地址实现有效监控。使用`arp`库安装(`npm install arp`)并编写代码,可定期扫描并对比设备列表,判断设备上线和下线状态。此技术适用于企业网络管理和家庭网络安全防护,未来有望进一步提升效率与准确性。
30 8
|
4月前
|
监控 JavaScript 算法
如何使用内存监控工具来定位和解决Node.js应用中的性能问题?
总之,利用内存监控工具结合代码分析和业务理解,能够逐步定位和解决 Node.js 应用中的性能问题,提高应用的运行效率和稳定性。需要耐心和细致地进行排查和优化,不断提升应用的性能表现。
230 77
|
2月前
|
JavaScript 算法 安全
深度剖析:共享文件怎么设置密码和权限的 Node.js 进阶算法
在数字化时代,共享文件的安全性至关重要。本文聚焦Node.js环境,介绍如何通过JavaScript对象字面量构建数据结构管理文件安全信息,包括使用`bcryptjs`库加密密码和权限校验算法,确保高效且安全的文件共享。通过实例代码展示加密与权限验证过程,帮助各行业实现严格的信息资产管理与协作。
|
2月前
|
存储 监控 算法
局域网网络管控里 Node.js 红黑树算法的绝妙运用
在数字化办公中,局域网网络管控至关重要。红黑树作为一种自平衡二叉搜索树,凭借其高效的数据管理和平衡机制,在局域网设备状态管理中大放异彩。通过Node.js实现红黑树算法,可快速插入、查找和更新设备信息(如IP地址、带宽等),确保网络管理员实时监控和优化网络资源,提升局域网的稳定性和安全性。未来,随着技术融合,红黑树将在网络管控中持续进化,助力构建高效、安全的局域网络生态。
58 9
|
3月前
|
监控 算法 JavaScript
基于 Node.js Socket 算法搭建局域网屏幕监控系统
在数字化办公环境中,局域网屏幕监控系统至关重要。基于Node.js的Socket算法实现高效、稳定的实时屏幕数据传输,助力企业保障信息安全、监督工作状态和远程技术支持。通过Socket建立监控端与被监控端的数据桥梁,确保实时画面呈现。实际部署需合理分配带宽并加密传输,确保信息安全。企业在使用时应权衡利弊,遵循法规,保障员工权益。
67 7
|
2月前
|
存储 监控 JavaScript
深度探秘:运用 Node.js 哈希表算法剖析员工工作时间玩游戏现象
在现代企业运营中,确保员工工作时间高效专注至关重要。为应对员工工作时间玩游戏的问题,本文聚焦Node.js环境下的哈希表算法,展示其如何通过快速查找和高效记录员工游戏行为,帮助企业精准监测与分析,遏制此类现象。哈希表以IP地址等为键,存储游戏网址、时长等信息,结合冲突处理与动态更新机制,确保数据完整性和时效性,助力企业管理层优化工作效率。
38 3
|
4月前
|
存储 缓存 监控
如何使用内存监控工具来优化 Node.js 应用的性能
需要注意的是,不同的内存监控工具可能具有不同的功能和特点,在使用时需要根据具体工具的要求和操作指南进行正确使用和分析。
97 31
|
4月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
104 1
|
4月前
|
JavaScript
如何使用内存快照分析工具来分析Node.js应用的内存问题?
需要注意的是,不同的内存快照分析工具可能具有不同的功能和操作方式,在使用时需要根据具体工具的说明和特点进行灵活运用。
83 3

热门文章

最新文章