作為對從未聽說過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內存架構
編碼愉快! 不要忘記分享!
拜倫
相關文章:
- Java最佳實踐系列
- 正確記錄應用程序的10個技巧
- 每個程序員都應該知道的事情
- 生存在狂野西部開發過程中的9條提示
- 軟件設計法則
- Java Fork / Join進行并行編程
翻譯自: https://www.javacodegeeks.com/2011/04/erlang-vs-java-memory-architecture.html