作为对从未听说过Erlang的人的真正的简短介绍; 它是一种功能语言,使用异步消息传递作为并发的基础。 消息传递使用复制语义,从而可以在多个以上的Erlang VM上分发,并且在对一台机器实质上透明的程序员上运行。
从某种意义上说, Erlang和Java都是相似的,它们都使用虚拟机将硬件抽象为可移植层。 两种语言都使用与机器无关的字节码。 两种运行时系统都依靠垃圾回收来释放程序员进行内存管理的能力。
Erlang中的线程开销非常低。 我相信Erlang中的线程的内存要求约为512字节。 在Java中,线程通常需要大约512 KB,大约是1000倍。 对于程序员来说,结果是创建线程来异步执行某些工作不是您必须坐下来思考的事情。 典型的Erlang系统具有成千上万的线程。 像我们在Java中那样,线程池和执行器没有麻烦。
从我所涉猎的内容来看,我发现Erlang是功能语言与允许您编写实际应用程序的语言之间的一种令人愉快的折衷。 (我知道我会为此感到迟疑)强大的分布式错误处理令人惊喜,编写任何类型的网络服务器实际上都很容易。 Web服务器的状态机方法使回滚错误变得完全自然。
但是这篇文章不是关于Erlang的编程模型的。 这是关于Erlang VM处理内存的方式。
当前的Java虚拟机使用Erlang程序员称为共享堆拓扑的东西。 所有线程都使用一个大堆。 大多数内存分配在该堆上。 除了堆之外,JVM还使用一些专用数据区域,例如代码缓存和永久生成。 这些也在所有线程之间共享。
相比之下, Erlang使用私有堆拓扑。 每个线程都有自己的微小堆,该堆包含该线程使用的所有数据以及该线程的堆栈。 线程的所有数据都在该本地堆上。 创建线程时保留它。 当线程死亡时,整个堆将简单地返回到空闲内存池。
除了私有堆之外,所有线程都共享对所谓的二进制堆和消息堆的访问。 这些是专门的堆。 二进制堆用于分配可能在线程之间共享的大块任意数据。 例如,这是文件输入或网络缓冲区所在的位置。
消息堆是消息中使用的数据的堆。 消息也在进程之间共享。 通过将指针从发送线程复制到接收线程,可以在线程之间传递消息。 消息的数据存储在消息堆上。
Erlang内存模型给我留下了深刻的印象。 它比Java的单堆模型具有更大的可扩展性。 语言语义和内存模型完美匹配。
例如; 堆是线程专用的一个简单事实可以减轻线程对自己数据的所有形式的锁检查的负担。 除此之外,没有破坏性的写操作,并且突然也不需要对共享数据进行锁定检查。
最新版本的Erlang VM通过拥有多个调度程序,进一步迈出了又一步。 确切地说,每个物理处理器一个调度程序。 这样就消除了另一类要检查的锁。 仅在无聊的调度程序时,它才需要出去,收集一个锁,并从另一个调度程序中获取一些进程。
在Java中,我们还有很多东西要学习。 就是说,我们在Java中有一些不错的东西,我错过了使用大型Erlang系统的情况。
当线程累积大量数据时, Erlang VM将重新分配并增加堆。 但是,重新分配算法导致堆大小快速增长。 在高负载下,我们已经看到Erlang VM在几分钟之内吞噬了16GB的RAM。 每个发行版都必须经过仔细的负载测试,以查看其内存需求是否仍然合理。
Erlang VM中没有任何机制可以抑制内存的增长。 VM会愉快地分配过多的内存,以至于系统需要进行交换,或者虚拟内存已用完。 这些可能会导致机器甚至无法响应KVM控制台访问。 过去,我们不得不关闭机器并重新启动,才能再次使用它们。
基于队列的编程模型使Erlang为其编写代码变得非常有趣,这也是生产中的致命弱点。 Erlang中的每个队列都是无界的。 VM不会引发异常或限制队列中的消息数。 有时,进程会由于错误而停止处理,或者进程无法跟上发送给它的消息流的速度。 在这种情况下, Erlang将只允许该进程的队列增加,直到VM被杀死或机器被锁定(以先到者为准)。
这意味着,当您在生产环境中运行大型Erlang VM时,您需要进行OS级别的检查,如果内存使用过多的话,这些检查将杀死进程。 对于运行大型Erlang VM的计算机,必须具有计算机的远程控制权或远程访问卡。
总之,对于每天的性能,我相信私有堆内存模型是Erlang盒子中非常强大的工具。 它将锁定机制的所有类都排除在运行时系统之外,这意味着在相同的目的下,它将比Java更好地扩展。 当系统被洪水或DDoSed攻击时,Java对内存的严格限制将节省您的培根。
最后的想法
Erlang的VM有一个命令行开关,可以将其从使用私有堆拓扑切换到使用共享堆拓扑。
我喜欢Erlang和Java。 它们之所以难以比较,是因为它们与开发人员的共同点很少。 通常,我会在大多数系统上使用Java。 工具支持更好,可用库的数量惊人。 如果我有一个面向流的消息传递系统,我会选择Erlang 。 那时, Erlang编程模型才真正发光。
参考文献:
- 我们的JCG合作伙伴Kees Jan Koster (来自Java-Monitor)的 Erlang内存架构与Java内存架构
编码愉快! 不要忘记分享!
拜伦
相关文章:
翻译自: https://www.javacodegeeks.com/2011/04/erlang-vs-java-memory-architecture.html