我对 Rust 借用检查器与 JVM 垃圾收集器的理解有一个基本问题。
我尝试深入了解 Java 中的各种垃圾收集实现(例如 G1 和 CMS)是如何工作的。我尝试浏览此资源以了解借用检查器实际上如何帮助 Rust 决定何时释放内存。
这是上面链接的 Rust 资源的一部分:
接下来,我们执行大量数据流分析,计算移动哪些数据以及何时移动。
然后,我们在 MIR 上进行第二次类型检查:此类型检查的目的是确定不同区域之间的所有约束。
接下来,我们进行区域推断,计算每个区域的值 - 基本上,根据我们收集的约束,控制流图中每个生命周期必须有效的点。
此时,我们可以计算每个点的“范围借用”。
我根本不明白的是,总的来说,“GC 语言由于 Stop the world 而导致性能非常糟糕” 的论点,是为什么这样的东西不能在 JVM 中实现?
理论上/证明不可能执行上面列出的相同步骤(“计算移动哪些数据以及何时移动的数据流分析”)来决定何时主动释放内存,而不是我们当前拥有的基于暂停的实现JVM?
事实是,完美是优秀的敌人。 JVM 已经很容易执行“逃逸分析”,这使得它能够优化永远不需要对象的对象的分配。例如,具有两个
Point
字段的 int
结构可以优化为堆栈上只有两个
int
值。逃逸分析是不完美的,并且常常无法证明不存在逃逸,但缺陷并不意味着它毫无用处:只要它成功证明不存在逃逸,它仍然有用!
您在此处引用的数据流分析(在 JVM 中)将是现有逃逸分析的变体或补充分析,并且可能会有所帮助。有时。
然而,Java 会成为障碍。 Rust语言
从一开始就在拥有值和引用/指针之间进行了明确的划分,因此数据流分析也具有这种区别。 Java 语言没有这种区别,因此任何对值的跟踪都更多更加复杂,并且最终成果要少得多。
最后,不要忘记 Rust 还具有 Rc
Arc
:引用计数指针,用于当静态作用域不足以表达应用程序逻辑时。 Java/JVM 也需要一些这样的动态机制。 GC就是这样一种机制。