`
deepinmind
  • 浏览: 451526 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
1dc14e59-7bdf-33ab-841a-02d087aed982
Java函数式编程
浏览量:41627
社区版块
存档分类
最新评论

Erlang和Java的内存模型比较

阅读更多
我读到一篇相当相当有趣的关于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编程模型大放异彩的时刻。


原创文章转载请注明出处:{{ page.title }}

英文原文链接
4
7
分享到:
评论
1 楼 white_crucifix 2014-03-13  
引用

IDE也许对某个框架支持的很好,但在最近一个版本中少了一个参数,你就不得不自己想办法解决。IDE很容易就能生成一系列代码,不过后面可能变得很难维护。这可能只是个很小的问题,但也是个问题——而编辑器是不会有这些问题的,因为它什么也没干。


哈哈,风趣

相关推荐

    java php python erlang 千万级内存数据性能比较

    例如,Erlang的进程模型和轻量级并发可能在处理大规模数据时提供优势;Java的JVM和内存管理策略允许处理更大规模的数据;PHP可能需要借助像Swoole这样的扩展来提升性能,"swoole_table_test.php"和"swoole.png"可能...

    程序员开发erlang的资料

    5. **Jinterface**:Jinterface是Erlang和Java之间的互操作库,它允许Erlang进程与Java虚拟机(JVM)中的对象进行通信。这对于既有Java基础又想利用Erlang优势的开发者来说,是一个强大的工具。 6. **Eclipse插件...

    并发需求下的Scala及Erlang语言的比较与使用

    Erlang的并发模型强调无共享内存和不可变数据结构,这使得它在处理高并发任务时能够有效避免数据竞争和死锁问题。 - **Scala**: Scala则是在JVM之上实现的Actor模型。Scala的Actor通过库(如Akka)实现,它们实际上...

    基于erlang的文件存储

    本项目“基于Erlang的文件存储”就是这样一个尝试,它利用Erlang强大的并发处理能力和分布式特性,为服务端提供稳定的基础架构,而客户端则通过Java的Swing组件提供用户友好的交互界面。以下是对该项目中涉及的技术...

    erlang和rabbitmq.zip

    在Erlang中,进程是轻量级的,每个进程都有自己的内存空间,相互之间通过消息传递进行通信,这种模型使得Erlang在处理并发和容错方面表现出色。 RabbitMQ是一个基于AMQP(Advanced Message Queuing Protocol)的...

    Programming Erlang second edition

    Erlang的并发模型不同于传统的线程模型,它不是共享内存而是通过消息传递,这有助于避免多线程编程中的锁竞争和状态共享问题。 Joe Armstrong在书中为读者提供了清晰和系统的解释,如何理解和使用Erlang的关键概念...

    Erlang otp_win64_21和22版本 exe

    - **混合系统**:Erlang OTP可以与Java平台结合,构建混合系统,利用两者的优点,例如Java的库丰富度和Erlang的并发性能。 5. **Erlang-otp_win64_21-22压缩包内容** - 可能包含Erlang OTP的完整安装程序,包括...

    Erlang环境,26.1.0.0和Erlang环境,26.1.0.0

    Erlang是一种面向并发的、通用的编程语言,由瑞典电信设备制造商Ericsson开发,主要用于构建...理解Erlang的并发模型和其在RabbitMQ中的作用,以及如何正确安装和配置这两个组件,是成功搭建和维护RabbitMQ服务的关键。

    erlang_win64_20.2.rar

    在实际应用中,Erlang的轻量级进程模型和自动内存管理使得RabbitMQ能够高效处理大量并发连接和高吞吐量的消息传递。RabbitMQ还支持集群,可以在多个节点之间复制数据,提高系统的可用性和容错性。 总的来说,这个...

    esl-erlang_23.0_windows版本和rabbitmq3.8.4 wendows版本

    1. **性能提升**:Erlang 23.0可能对虚拟机进行了优化,提高了运行速度和内存管理效率。 2. **新语言特性**:新版本可能包含新的语法或编程模型,以提高代码的简洁性和可读性。 3. **库更新**:OTP库可能有升级,...

    rabbitmq3.3.7 +erlang_21.0.1

    Erlang的并发模型和垃圾回收机制使得RabbitMQ能够处理大量的并发连接和高吞吐量。 为了在CentOS 6或7上部署RabbitMQ 3.3.7和Erlang 21.0.1,你需要执行以下步骤: 1. **安装Erlang**:首先,你需要安装Erlang的...

    erlang版本的protobuf(erl_protobuffs)

    2. **内存管理**:Erlang的垃圾回收机制与C++或Java不同,`erl_protobuffs`充分利用了这一特性,优化了内存管理和对象生命周期,减少了不必要的内存开销。 3. **集成性**:由于Erlang主要用于构建分布式系统,`erl_...

    Erlang和RabbitMQ 消息队列

    1. **并发性**:Erlang的并发模型是基于轻量级进程(processes)的,这些进程之间通过消息传递进行通信,而非共享内存。这使得Erlang非常适合构建高并发、容错性强的系统。 2. **故障恢复**:Erlang的BEAM虚拟机...

    RabbitMQ+ erlang32位系统.rar

    1. **并发处理**:Erlang的轻量级进程模型使得RabbitMQ能高效处理大量并发连接和消息。 2. **分布式特性**:Erlang支持分布式计算,使得RabbitMQ可以轻松地在多台机器上部署为集群,提供高可用性和故障转移能力。 3....

    RabbitMQ+ERLANG.zip

    Erlang的进程模型允许成千上万个轻量级进程同时运行,每个进程都有自己的内存空间,这样可以有效隔离错误,增加系统的健壮性。此外,Erlang的错误恢复机制使得系统能够在部分节点失败后快速恢复,这对于构建高可用的...

    Erlang and OTP in Action

    它的并发模型基于进程,每个进程拥有独立的内存空间,通过异步的消息传递进行通信,这种模型非常适合处理大量并发连接。Erlang的语法简洁,动态类型使得开发过程更为灵活,而其强大的错误恢复机制能确保系统在出现...

    RabbitMQ+erlang

    - **并发性**:Erlang进程模型使得在单个节点上并行运行大量轻量级进程成为可能,这些进程通过消息传递进行通信,减少了竞争条件和同步问题。 - **热代码替换**:Erlang支持在运行时更新和升级代码,无需重启服务,...

    (学成在线day05 RabbitMQ资料)Erlang/OTP20.3版本和RabbitMQ3.7.3

    Erlang的并发模型、轻量级进程和热代码升级特性使其在处理大量并发连接和高可用性场景下表现出色。 2. **OTP**:OTP是Erlang的一个重要组成部分,它提供了一套标准库、开发工具和设计原则,帮助开发者构建可伸缩、...

    Erlang Programming

    2. **系统容错性**:Erlang 的设计使得系统能够容忍软件错误和硬件故障,这主要得益于其独特的进程模型和故障隔离机制。 3. **在线更新**:Erlang 支持热更新(Hot Swap),即在不中断服务的情况下进行软件更新。 ...

    Erlang安装手册

    它拥有一个独特的运行时环境,类似于Java虚拟机(JVM),使得编译后的Erlang代码可以在任何支持该虚拟机的平台上运行而无需重新编译。这种特性极大地简化了部署过程,并提高了代码的便携性。 #### 二、Erlang的核心...

Global site tag (gtag.js) - Google Analytics