Erlang与java的内存架构比较
http://blog.sina.com.cn/s/blog_541086000100qod1.html
?我讀了一篇非常非常有趣的文章(Jesper Wilhelmsson的一篇論文),是關于Erlang 虛擬機(Erlang VM)內存管理策略的。我相信對比一下Erlang和java的虛擬機內存管理策略,一定很有意思。
???????先給從來沒有聽說過Erlang的同學做個簡短的介紹。Erlang 是一門函數語言,通過異步消息傳遞(asynchronous message passing)來處理并發,使用語義拷貝(copy semantics)傳遞消息。即使Erlang分布在多個虛擬機上,運行在多臺機器上,對程序員來說也是透明的。
???????在某種意義上Erlang和java是相似的,他們都通過虛擬機來獲得可移植性,都采用獨立于操作系統的字節碼技術,都使用垃圾回收機制來解脫程序員自己管理內存的麻煩。
???????Erlang中線程的開銷是非常低的。我相信在Erlang中,一個線程只需要大約512字節的內存。而java線程則需要512K字節的內存,大約是Erlang的一千倍多。對程序員來說,這意味著創建一個線程非常輕便。典型的Erlang系統中可以有上萬的線程。所以Erlang不需要做線程池、executors等等,那些我們寫java多線程要用到的東西。
???????在我過去很少涉獵的語言中,我發現Erlang既保持了函數語言的特性,又能夠做出真正的應用來。Erlang健壯的分布式錯誤處理非常驚艷,讓編寫任何一種網絡服務變得相當容易。這種狀態機的處理方式使web 服務在出錯時,處理回滾非常自然。
???????不過這篇文章不打算討論Erlang的編程模型,這里主要想討論Erlang虛擬機的內存管理方式。
???????目前java虛擬機采用了一種被Erlang程序員稱作“共享堆”的機制,虛擬機維護了一個可以被所有線程共享和使用的大堆(堆和棧什么區別)。這個堆占用了虛擬機的大部分內存。在這個大堆里,也包括了虛擬機的一些特殊數據區域,例如代碼緩存和永久區。這些特殊數據區也是被所有線程共享的。
???????相反的,Erlang使用一種私有堆的技術。每個線程都有一個只屬于自己的小堆,里面包含了這個線程用到的所有數據以及線程棧。這個堆是在線程被創建的時候分配的。當這個線程結束了,它的私有堆內存就被虛擬機收回了。
???????除了私有堆,Erlang中所有的線程都能訪問兩個特殊的堆,二進制堆和消息堆。二進制堆被分配了大量的數據塊,以便線程線間共享數據。例如文件輸入或是網絡緩沖區。
???????消息堆里放的是消息(messages)數據。這些消息也可以在進程間共享。線程之間傳遞消息的方式,是從發送線程復制一個指針到接收線程。這些消息數據就被存放在消息堆里。
???????我對Erlang的內存模型印象深刻。被它比java更具擴展性的內存模型給震撼了。而且這門語言的語法和他的內存模型結合的非常漂亮。
???????因為有私有堆,Erlang線程對自己的數據檢查不需要采用任何形式的鎖。并且私有堆也避免了破壞性的寫,這樣也就沒有了對共享數據加鎖的需求。
????????最新版的Erlang又往前走了一步,采用了多個調度器(scheduler)。每個物理處理器有一個調度器可以保證更精確。而且這也消除了另一種需要檢查的鎖。僅當一個調度器無用了,才會用到鎖,以便從其他處理器上獲得一個新的調度器。
???????關于java,我們仍然有很多東西要去學習。也是就說,java里還是有些好東西的,也正是因為這點,我才沒有使用大型的Erlang系統。
???????當Erlang線程積累了大量數據的時候,Erlang虛擬機會重新分配空間,擴大私有堆。然而,這個重新分配的算法會導致堆空間急速增長。在高負載下,我們看到Erlang虛擬機在幾分鐘內吃掉了16G的內存!每次發布版本都要小心的做負載測試,看看它的內存需求是否能被滿足。
???????Erlang虛擬機沒有抑制內存增長的機制。虛擬機不斷的分配內存,迫使系統不得不使用交換區(swap),直到虛擬內存被耗盡。這可能會導致用KVM控制臺訪問系統變得很遲鈍。使我們不得不重啟系統,才能夠再次訪問它。
???????基于隊列的編程模型讓Erlang編程變得非常愉快,但這也是Elang系統設計上的致命缺陷。Erlang的每一個隊列都是無界的。虛擬機不會拋出異常,也不會限制一個隊列的消息數量。有時候會出現,一個進程可能由于bug而停止工作,或者進程消費消息的速度跟不上消息發送速度的情況。在這種情況下,Erlang還是允許這個進程的消息隊列不斷的增長,直到虛擬機被殺掉,或是這個機器被鎖死了。
???????這意味著當你在生產環境運行Erlang虛擬機時,要配備一個系統級的檢測,以便在Erlang內存使用量飛漲的時候能夠殺死進程。所以,運行大型Erlang應用的機器需要能被遠程訪問和操作(是不是意味著需要經常上去處理問題??)。
???????總的來說,我認為在Erlang的工具箱里,“私有堆”是一個非常強大的工具。它避免了實時系統里的鎖機制,這個意味著它將比java更具擴展性。而java的硬性限制內存的模型,則能在你的系統壓力劇增,或是遭受DDOS攻擊的時候保持穩定。
???????有一個命令行,可以將Erlang的虛擬模型從“私有堆”改成“共享堆”。
???????我喜歡Erlang和java。但他們很難進行比較,因為對開發者來說,他們的共同點很少。一般情況下,我在大多數系統里使用java。因為它有很好的工具支持,而且有大量的lib包可以使用。當我需要一個面向信息流的系統時,我會使用Erlang。這才是Erlang模型真正放光芒的時候。
總結
以上是生活随笔為你收集整理的Erlang与java的内存架构比较的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RMI原理及开发实例
- 下一篇: 实现java RPC框架