原文  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. win7打开ftp步骤

    FTP是很方便文件传输的功能 打开ftp xftp连接 传输测试 如果连接不通的话,有可能是防火墙的问题

  2. 独家git clone 加速方法

    git clone 独家方法 最近需要下载网上很多github库,所以git clone 4kb/s 的速度可以把人逼疯,为了加速git clone才有了这篇博客 网上有很多加速的方案 比如 blog ...

  3. python 这个stdin怎么写

    !/usr/bin/env python -- coding: utf-8 -- import json import pprint import sys reload(sys) sys.setdef ...

  4. nRF5芯片外设GPIO和GPIOTE介绍

    nRF51/nRF52同时包含GPIO和GPIOTE两种外设,经常有人将两者搞混,今天我们就来介绍一下这2种外设有什么不同,及使用注意事项. GPIO和GPIOTE都属于芯片外设,但两者功能完全不一样 ...

  5. 20165332实验四 Android开发基础

    20165332 实验四 Android程序设计 一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:延亿卓 学号:20165332 指导教师:娄嘉鹏 实验日期:2018年5月14日 实 ...

  6. Android6.0------权限管理

    此博客主要谈谈Android6.0的权限,关于其他6.0的知识 请看https://developer.android.com/about/versions/marshmallow/android-6 ...

  7. MongoDB基于GridFS管理文件

    前言 GridFS是一种将大型文件存储在MongoDB的文件规范: 数据库支持以BSON格式保存二进制对象. 但是MongoDB中BSON对象最大不能超过4MB. GridFS 规范提供了一种透明的机 ...

  8. LM3S之boot loader学习笔记-2

    LM3S之boot loader学习笔记-2 彭会锋 () 上一篇中介绍了bootloader的基础知识,对于bootloader的作用和如何编写bootloader也有了大概的了解了,这一篇主要讲解 ...

  9. 你真的掌握 LVS、Nginx 及 HAProxy 的工作原理吗

    你真的掌握 LVS.Nginx 及 HAProxy 的工作原理吗 当前大多数的互联网系统都使用了服务器集群技术,集群是将相同服务部署在多台服务器上构成一个集群整体对外提供服务,这些集群可以是 Web ...

  10. HDU5521-最短路-建图

    Meeting Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...