原文  http://deepinmind.iteye.com/blog/2030390

我读到一篇相当相当有趣的关于Erlang VM内存管理策略的文章。它是Jesper Wilhelmsson写的一篇论文,我觉得有必要讨论一下Erlang和Oracle的Java虚拟机在内存管理方面的不同之处。 
对于从没听说过Erlang的人来说,有必要简单的介绍一下,它是一门函数式语言,并且使用异步消息传递作为它并发的基石。消息传递使用的是拷贝的机制,并且在不同的Erlang虚拟机中传播,甚至是在不同的机器上(不过这个对程序员来说是透明的)。 
Erlang和Java都通过虚拟机将底层硬件抽象成了一个可移植的平台。两门语言都采用了独立于机器的字节码。两者的运行时系统都通过垃圾回收来将程序员从内存管理中解放出来。 
Erlang的线程开销非常的低,我认为Erlang的一个线程大概只需要512字节。在Java里线程大概需要512KB,差不多是1000倍。对于Erlang程序员来说,创建线程来异步处理些任务简直太平常不过了。通常来说Erlang的系统都成千上万的线程在同时工作着。不像Java那样,我们得在线程池和executors上面浪费时间。 
通过我对Erlang的一点点玩票,我发现Erlang在一门函数式语言和一门可以实际写程序的语言里面作了一个很好的折中(我知道这么说肯定会被喷的很惨)。健壮的分布式错误处理令人惊喜,随便编写什么网络服务器都变得非常简单。WEB服务器的状态机使得错误回滚看起来如此自然。 
不过这篇文章并不是要讲Erlang的编程模型的。它是要介绍Erlang虚拟机如何来管理内存。 
现在的Java虚拟机用的是一种Erlang程序员称之为共享堆的机制。所有线程共享一个大的堆。大部分内存都是在那个堆上分配的。除了这个堆外,JVM也使用了一些专用的数据区域比如代码缓存还有持久代。这些也是所有线程共享的。 
相反的,Erlang用的是一个私有堆的拓扑结构。每一个线程都有一个专属的小堆,里面包含了这个线程用到的所有数据,线程的栈也在这里面。线程的所有数据都在这个本地堆上。当线程创建的时候这个堆就预留出来了。如果这个线程结束了,就把整个堆都扔回到空闲内存的池子里面。 
除了私有堆外,所有线程都共享一个称为二进制堆的以及一个消息堆。这些都是有特殊用途的堆。二进制堆用来分配有可能在线程间共享的任何大块数据。比如文件或者网络缓存都在这个区域。 
消息堆是指消息数据的堆。消息也是在进程间共享的。消息在线程间传递只是从发送线程拷贝了一个消息指针传到接收线程。消息数据是存储在消息堆里的。 
Erlang的内存模型令我印象深刻。和Java的单个堆的模型相比,它的伸缩性要强得太多了,这点让我触动很深。语言的语义和内存模型完美的结合到了一起。 
比如说,线程拥有私有堆可以使得线程从各种检查自身数据的锁中解放出来。更进一步的,破坏性的写入也成为了过去,也不再需要加锁来检查共享数据了。 
最近一版的Erlang虚拟机还做了一件事是,引入了不止一个的调度器。每个物理处理器使用一个调度器来确保精确,这样避免了使用全局锁来进行检查。除非有个调度器太闲了,才会去获取个锁,然后从别的调度器那抢点活过来干干。 
不过在Java,还有很多是值得Erlang借鉴的。就是说,Java里有一些好的特性,而Erlang现在还没有。 
当线程的堆积累的数据过多的时候,Erlang虚拟机会重新分配堆并增加它的大小。然而重新分配的算法会导致堆迅速的膨胀。在高负载下,Erlang的虚拟机能在短短数分钟内吃掉16G的内存。每个发布的版本都应该严格进行压测以确保能够合理的使用内存。 
Erlang的虚拟机里还没有机制能够抑制内存过快的增长。虚拟机很乐于为分配内存而效劳,以至于系统瞬间就进入到交换分区,也就是说虚拟内存也被榨干了。这会导致机器无法响应,甚至连KVM的控制台也无法访问。之前我们只能重启机器电源才能重新访问。 
基于队列的编程模型使得Erlang编程变得非常有趣,不过在生产环境中,这也是它的致命的弱点。Erlang中的队列都是无限大小的。虚拟机不会抛出异常也不会限制队列中消息的数量。有的时候线程会由于出现BUG而无法继续处理,有的时候线程的处理速度赶不上消息的发送速度。万一出现了这种情况的话,Erlang只会放任队列不断增长,直到虚拟机被杀死或者机器锁住,就看哪个先来了。 
这就意味着当你在生产环境中运行大型的Erlang应用的时候,你得在操作系统层面来确保如果内存出现井喷能够把进程杀掉。在运行大型Erlang虚拟机的机器上,远程控制器或者远程访问卡都是必备良药。 
总而言之,我相信Erlang里的私有堆的内存模型对于日常的性能而言是一个非常强大的工具。它从运行时系统里砍掉了大量的锁的机制,这样在同样的应用下,Erlang系统的伸缩性要比Java要强得多。而Java在内存上的硬性的限制会让你的应用在面临DDoS攻击的时候能让你幸免于难。 
最后说一点,Erlang有个命令行开关能让它从私有堆切换到共享堆。 
Erlang和Java我都很喜欢。对于开发者而言它们很难进行比较,因为它们几乎没有什么共同之处。不过在通常情况下,我还是会用Java来开发系统。因为它在工具支持方面要更好,同时还有多的让人难以置信的第三方库。如果有个面向流的消息系统,我会考虑使用Erlang。这才是Erlang编程模型大放异彩的时刻。

erl_0021 erlang和java的内存模型比较(引用)的更多相关文章

  1. java线程内存模型,线程、工作内存、主内存

    转自:http://rainyear.iteye.com/blog/1734311 java线程内存模型 线程.工作内存.主内存三者之间的交互关系图: key edeas 所有线程共享主内存 每个线程 ...

  2. Java虚拟机内存模型及垃圾回收监控调优

    Java虚拟机内存模型及垃圾回收监控调优 如果你想理解Java垃圾回收如果工作,那么理解JVM的内存模型就显的非常重要.今天我们就来看看JVM内存的各不同部分及如果监控和实现垃圾回收调优. JVM内存 ...

  3. java String 内存模型

    关于java的内存模型,参照以下的一篇文章: https://isudox.com/2016/06/22/memory-model-of-string-in-java-language/

  4. Java虚拟机--内存模型与线程

    Java虚拟机--内存模型与线程 高速缓存:处理器要与内存交互,如读取.存储运算结果,而计算机的存储设备和处理器的运算速度差异巨大,所以加入一层读写速度和处理器接近的高速缓存来作为内存和处理器之间的缓 ...

  5. 掌握Java的内存模型,你就是解决并发问题最靓的仔

    摘要:如果编写的并发程序出现问题时,很难通过调试来解决相应的问题,此时,需要一行行的检查代码,这个时候,如果充分理解并掌握了Java的内存模型,你就能够很快分析并定位出问题所在. 本文分享自华为云社区 ...

  6. Java对象内存模型

    2 Java对象内存模型 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header). 实例数据(Instance Data)和对齐填充(Padding). 在 JVM ...

  7. 全网最硬核 Java 新内存模型解析与实验单篇版(不断更新QA中)

    个人创作公约:本人声明创作的所有文章皆为自己原创,如果有参考任何文章的地方,会标注出来,如果有疏漏,欢迎大家批判.如果大家发现网上有抄袭本文章的,欢迎举报,并且积极向这个 github 仓库 提交 i ...

  8. Java线程内存模型-JVM-底层原理

    public class Demo1 { private static boolean initFlag=false; public static void main(String[] args) t ...

  9. Java虚拟机 - 内存模型

    本文主要介绍Java虚拟机的内存分布以及对象的创建过程. 一.Java虚拟机的内存分布 文章开始前读者需要了解Java虚拟机的运行时数据区是怎样划分的.如下图所示: 1.程序计数器(Program C ...

随机推荐

  1. SpringBoot中使用log4j日志

    一:引入jar包 使用SpringBoot创建项目的时候,pom文件引入了spring-boot-starter,其中包含了spring-boot-starter-logging,该依赖内容就是Spr ...

  2. u-boot-2015.07 make xxx_config 分析

    1.u-boot编译脚本:mk.sh #! /bin/sh export PATH=$PATH:/opt/ti-sdk-am335x-evm-08.00.00.00/linux-devkit/sysr ...

  3. FlashFXP客户端 FTP连接,连接很慢的情况,

    菜单栏-->站点-->站点管理器--->左边视图FTP--->列表命令选择 STAT -L

  4. python学习大纲目录(转自alex博客https://www.cnblogs.com/alex3714/)

    day01: 介绍.基本语法.流程控制 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc是个什么鬼? 数据类型初识 数据运算 ...

  5. 使用Idea工具nodeJS+mysql开发项目

    一.MySQL Server的安装 1.mysql官网下载文件包:[我使用的版本是:mysql_5.7.17] 2.解压Zip压缩包: 3.安装:命令行:D:\soft\mysql-5.7.17-wi ...

  6. UVALive - 6709树套树

    题意:给你一个矩阵,q次操作,每次查询长宽l的矩阵最大值a和最小值b,然后把中间点换成floor((a+b)/2), 解法:暴力可过,建n颗线段树暴力更新,但是正解应该是树套树,树套树需要注意的是当建 ...

  7. 第一阶段考试:实战Linux系统日常管理

    1. [项目名称] 实战Linux系统日常管理 [项目说明] 1.安装部署rhel系统,组建RAID磁盘阵列. 2.安装nginx 通过脚本编写 nginx服务服务启动脚本 [项目考核技能点] 1.安 ...

  8. Python绘图技巧

    转自:https://www.cnblogs.com/zhizhan/p/5615947.html Python--matplotlib绘图可视化知识点整理 强烈推荐ipython 原文:http:/ ...

  9. BZOJ 1026 windy数 (数位DP)

    题意 区间[A,B]上,总共有多少个不含前导零且相邻两个数字之差至少为2的正整数? 思路 状态设计非常简单,只需要pos.limit和一个前驱数pre就可以了,每次枚举当前位时判断是否与上一位相差2即 ...

  10. IOS-源代码管理工具(SVN)

    一.使用环境 要想利用SVN管理源代码,必须得有2套环境 服务器 用于存储客户端上传的源代码 可以在Windows上安装Visual SVN Server 大部分情况下,公司的开发人员不必亲自搭建SV ...