BEAM 和 JVM 之间有哪些基本的功能/架构差异?
- 是的,我知道:一个最初是围绕 java 构建的,另一个是围绕 erlang 构建的
- 我了解 JVM(有点)并想比较它们的结构
- 例如,我知道 JVM 有一个全局 GC,而 BEAM 每个进程有一个
BEAM 和 JVM 之间有哪些基本的功能/架构差异?
首先,Beam 是一台寄存器机,而不是堆栈机。与 Prolog 的 WAM 一样,它使用“X-registers”作为普通寄存器(在 C 中作为数组实现),以及“Y-registers”作为本地函数激活记录中的插槽名称(“调用帧”)在堆栈上。没有堆栈操作指令。
其次,有快速分配更多堆内存的指令,用于初始化堆上的元组和其他数据结构,用于选择元组的元素等。JVM专注于对象,并且具有隐藏的“新”操作内存分配和基本初始化的细节。
BEAM 有一条指令,用于递减进程的“减少计数器”并决定是否该让步以让另一个进程运行。另一方面,JVM 具有线程同步指令。
一个重要的区别是 BEAM 有尾调用指令,这是 JVM 所缺乏的。
最后,对于 BEAM 和 JVM,目标文件中使用的指令集实际上只是一种传输格式。BEAM 仿真器将文件中的指令重写为具有许多优化的特殊情况指令的内部版本(可以从一个版本更改为另一个版本)。或者,您可以编译为本机代码。大多数 JVM 都做同样的事情。
其他一些有趣的点是:
进程是 BEAM 公民,由 VM 本身管理,而 JVM 将其管理委托给操作系统。这允许 BEAM 非常快速地管理(创建、删除、上下文切换……),因此能够管理数十万个进程,而不是在一台合理的机器上管理数百个 java 线程。
在 BEAM 上,进程间通信基于消息交换,它消除了大多数(如果不是全部)可能导致竞争条件的情况。在 Java 上,您需要同步线程,这很困难且容易出错。
重要的一点是垃圾收集是在 BEAM 中的每个进程的基础上完成的,而它是 JVM 中的全局进程。其影响是 JVM 上的 GC 可能会将整个 VM 冻结几秒钟,而在 BEAM 上,每个进程必须将其一些执行操作(减少)交给 GC,而不影响其他进程。
最近,一些针对JVM语言的新库,比如VertX(我不太了解Akka,但我相信是这样)开始实现类似的进程行为,试图解决问题1和2。我相信GC的问题不能不过,通过库简单地解决了。