内存
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进行对调,如此往复。
这里有一个注意点,是将存活着的对象按顺序复制到To中,为什么不选择直接删除From部分非存活对象呢?这是因为如果直接删除非存活对象,会产生内存碎片的问题,使得可用空间减小,新生代回收算法选择了牺牲部分空间来换取时间,提高了回收速度。
老生代
当新生代的对象经过一次回收或者是发现本次复制后,会占用超过25%的To空间,则会将对象放入老生代中。
老生代的回收机制包括以下几个步骤:
- 标记可达对象
- 清除未标记对象
- 整理内存空间
由于老生代的空间较大,对于一些大型的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
在执行完一次代码或者是内存不够时,将会触发垃圾回收,因此需要注意两点
- 尽量减少使用全局变量,因为全局变量在程序执行完毕后才会回收,如果必须使用,则可以在某些时刻进行手动的示范。
- 注意闭包的使用,要注意闭包的无限增长。