垃圾回收Safepoint机制

垃圾回收算法通常都有个阶段要暂停所有线程对内存对象引用关系网络的更新,这个机制称为Safepoint。所有线程达到Safepoint所需要的时间对垃圾回收的总体暂停时间有很大影响。

要暂停一个线程的执行有两个途径,一个是协作式的(非抢占式),一个是抢占式的。用户态的线程可以被处于核心态的时钟中断抢占(从而完成调度)。但是用户态的线程怎么能被同样处于用户态的垃圾回收线程抢占呢?所有通常只能采用协作式的方式,让线程自己暂停。

基本的思想是设置一个全局变量作为暂停标记,每个线程时不时的去检查一下这个标记看是不是需要暂停。当然越快停下越好,但是也不能时时刻刻检查浪费CPU。

JVM运行的几种类型的代码有自己的检查这个标记的方式:

(1)对于正常解释执行的Java字节码。此时解析器会在执行每条指令前做检查(可以做些优化)。

(2)JNI代码。如果JNI代码不和JVM交互,实际上可以不用暂停继续执行,但是一旦调用JVM代码就会检查暂停标记。

(3)JIT编译出来的机器码。此时会在编译的代码中插入检查暂停标记的代码,比如在方法调用或者循环语句中。

HotSpot JVM以一种比较特殊的方式来检查暂停标记。这个标记放在一个特殊的内存位置。当需要暂停的时候,JVM把这块内存unmap掉,从而触发中断,JVM处理这个中断,然后把线程挂起。

http://blog.ragozin.info/2012/10/safepoints-in-hotspot-jvm.html

Go的做法是类似的,一开始只能在函数调用时检查暂停标记,后来增加了在循环中检查。

https://github.com/golang/go/issues/10958

但是Go对于Safepoint检查带来的性能影响不太满意,所以计划实现抢占式方式。 其实“用户态的线程怎么能被同样处于用户态的垃圾回收线程抢占”还是有可能的,可以利用信号来实现,具体怎么做还不是太清楚。

https://github.com/golang/go/issues/24543

原文 

https://studygolang.com/articles/17306

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 垃圾回收Safepoint机制

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址