Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

14. v8垃圾回收机制 #15

Open
linrunzheng opened this issue Aug 17, 2021 · 1 comment
Open

14. v8垃圾回收机制 #15

linrunzheng opened this issue Aug 17, 2021 · 1 comment

Comments

@linrunzheng
Copy link
Owner

v8采用分代式垃圾回收机制,根据对象的存活时间将内存中的垃圾进行不同的分代,不同的分代采用不同的垃圾回收算法。

v8内存结构主要分为两种:

  • 新生代
  • 老生代

新生代

新生代主要用于存放存活时间较短的对象,新添加的对象通常会先放进新生代。新生代主要采用了Scavenge算法,它会将内存分为两个区域,激活区域和非激活区域,也即From区域和To区域,两个区域始终只有一个处于激活状态。对象首先会进入From区域,当进行垃圾回收时,如果From区域尚有存活对象,则会将存活对象复制到To区域,之后会清空From区域并将From区域和To区域的角色互换,等待下一轮垃圾回收。(不停的复制以及交换空间)

对象晋升

当一个对象在经历了多次复制之后仍然存在,那么就会被认为是一个生命周期比较长的对象,在进行下一次垃圾回收时会将其转移到老生代,即所谓的对象晋升;

老生代

老生代主要采用了标记清除算法,它分为标记以及清除2个阶段。标记阶段会从根节点遍历所有可以访问到的子节点并将其标记为活动对象,对于根节点不能访问到则为非活动对象,视为垃圾。在到了清除阶段时,会将非活动对象进行清除,回收其占用的内存归还操作系统。

在经历过标记清除之后,内存空间可能出现不连续的状态,因为我们清除的对象的内存地址通常不是连续的,从而导致出现内存碎片的问题,后面要分配大的内存的时候可能会因为碎片的存在而导致内存不足,因此v8又引入了标记整理算法,在清除非活动对象之后,会将活动对象往内存的一端移动,并将另一侧的内存全部清除,由此完成一次老生代的垃圾回收。

由于javascript单线程的缘故,执行垃圾清除时会阻碍主线程同步任务的执行,如果垃圾回频繁且回收时间过长,则会造成卡顿。为此v8又引入了增量标记的概念,每次只标记一部分则暂停并将执行权归回主线程,之后从上次暂时的地方继续进行标记,直到标记完全部内存。

@linrunzheng
Copy link
Owner Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant