网易课程学习——JS进阶(内存)

231 阅读3分钟

内存

V8内存

64位下是1.4G,32位下是700MB,但是根据浏览器的不同,有些许扩容。

Node情况下会有一下C++的内存扩容。

为何V8要设置为1.4G?首先是因为1.4G对于浏览器脚本来说是够用的,其次由于JS是单线程的,当垃圾回收时是阻塞式的,所以过大的话进行垃圾回收时,会造成应用卡顿。

内存分为新生代与老生代

  • 新生代:短时间存货的新变量存放在新生代中,64位下内存大概为32MB,32位下减半。
  • 老生代:生存时间比较长的变量会转存到老生代中,64位下内存大概为1400MB,32位下减半。

新生代

![CE~4AAHU9X)~CO)K_YTQ4A.png

新生代分为From和To两个部分,其中From表示正在使用的部分,To表示暂时闲置的部分。

新生代的回收算法:首先将From部分的对象检查一遍,将存活着的对象按顺序复制到To中,然后将From清空,最后将From和To进行对调,如此往复。

BAES_E6H6682$D{OXLVPX.png

这里有一个注意点,是将存活着的对象按顺序复制到To中,为什么不选择直接删除From部分非存活对象呢?这是因为如果直接删除非存活对象,会产生内存碎片的问题,使得可用空间减小,新生代回收算法选择了牺牲部分空间来换取时间,提高了回收速度。

老生代

当新生代的对象经过一次回收或者是发现本次复制后,会占用超过25%的To空间,则会将对象放入老生代中。

老生代的回收机制包括以下几个步骤:

  1. 标记可达对象
  2. 清除未标记对象
  3. 整理内存空间

由于老生代的空间较大,对于一些大型的Web应用程序,标记整个内存可能需要花费100ms以上的时间,为了避免长时间中断主线程,V8 长期以来具有以许多小步长增量标记活动对象的能力,目的是使每个标记步长的持续时间保持在 5 毫秒以下。当标记结束后,将会清除老生代内存,最后进行老生代内存空间的整合,将存活的对象往一端进行移动,将解决内存碎片。

内存优化

对于浏览器端,可以使用window.performance.memory来进行内存的查看。

对于Node端,可以使用process.memoryUsage()来查看内存的使用情况,且可以通过

node --max-old-space-size=1024 xxx.js //设置老生代的内存 MB

node --max-new-space-size=1024 xxx.js //设置新生代的内存 KB

在执行完一次代码或者是内存不够时,将会触发垃圾回收,因此需要注意两点

  1. 尽量减少使用全局变量,因为全局变量在程序执行完毕后才会回收,如果必须使用,则可以在某些时刻进行手动的示范。
  2. 注意闭包的使用,要注意闭包的无限增长。