GC介绍
Last updated
Was this helpful?
Last updated
Was this helpful?
我们当然是希望以上过程能跟我们的主协程并行, 这样的话就不会有STW, 也就不会产生任何损失了, 但如果以上过程真的是并行了, 会产生一些问题, 这里我们描述一种黑白相连的问题:
我们的整理工作是按照"回合"进行的, 假设现在存在一个灰色的点链接着一个白色的点, 那么按照上面的步骤, 下一回合这个白色的点也将被标记成灰色的点, 从而被保留下来.
但就在这个时候, 突然这个链接被断开, 这个白色的点被连上一个黑色的点. 按照三色标记的工作方式, 我们已经不会在到访这个黑色的点了, 同样这个白色的点也不会再标灰了. 那么这个白色的点, 就算被黑色的点所引用, 是有效的, 同样会被清理. 等到黑点想要用这个白点的时候会造成数据丢失.
写屏障开启后 → 对于任何尝试黑白相连的操作, 直接把白点置灰就完事了. 虽然我不知道这个白点是不是有效的, 但我乐观的相信你是有效的, 就算你是无效变量, 你活的过这一轮同样活不过下一轮
如果我们并行写屏障策略能解决我的问题吗? 不能, 因为写屏障只能管的到堆, 管不到栈. 也就是说栈上的垃圾我们还是需要STW来清理一下.
如果你他妈非要深究为什么只能管的到堆管不到栈: 我们在内存分布里说过, 变量有的是在堆上有的在栈上, 有的在栈上的变量也会逃逸到堆上, new
出来的变量本质上是通过alloc()
往堆上分配内存, 这个函数会阅读当前的GC状态, 如果写屏障开启, 则分配出来的变量一定置灰. 而栈上内存分配的函数则不会用到这个函数, 这也导致我们无法对栈上新分配的内存进行有效的管理
删除屏障开启后 → 对于任何尝试灰白断连的操作, 直接将白点置灰就完事了, 因为没有灰白断连, 就不会再有黑白相连. 这种操作脑回路上跟写屏障是一样的, 你们在不知道这个白点的情况下就直接置灰, 不过没关系, 如果这是个无效数据, 同样是活不过下一轮的.
如果我们并行删除屏障能解决我们STW的问题吗? 不能, 删除屏障需要在一开始为堆栈做快照, 然后并行分析并删除, 其中做快照的时间是要STW的
删除屏障确实没解决什么问题, 但删除屏障带来一种新思路, 搞快照:
写屏障能解决堆的问题, 所以我们让写屏障并行
栈的问题可以由删除屏障解决, 虽然删除屏障需要STW搞快照, 我们不搞堆+栈整体的快照, 我们只照栈节省时间