Erlang与Java内存架构
作為對(duì)從未聽(tīng)說(shuō)過(guò)Erlang的人的真正的簡(jiǎn)短介紹; 它是一種功能語(yǔ)言,使用異步消息傳遞作為并發(fā)的基礎(chǔ)。 消息傳遞使用復(fù)制語(yǔ)義,從而可以在多個(gè)以上的Erlang VM上分發(fā),并且在對(duì)一臺(tái)機(jī)器實(shí)質(zhì)上透明的程序員上運(yùn)行。
從某種意義上說(shuō), Erlang和Java都是相似的,它們都使用虛擬機(jī)將硬件抽象為可移植層。 兩種語(yǔ)言都使用與機(jī)器無(wú)關(guān)的字節(jié)碼。 兩種運(yùn)行時(shí)系統(tǒng)都依靠垃圾回收來(lái)釋放程序員進(jìn)行內(nèi)存管理的能力。
Erlang中的線程開(kāi)銷非常低。 我相信Erlang中的線程的內(nèi)存要求約為512字節(jié)。 在Java中,線程通常需要大約512 KB,大約是1000倍。 對(duì)于程序員來(lái)說(shuō),結(jié)果是創(chuàng)建線程來(lái)異步執(zhí)行某些工作不是您必須坐下來(lái)思考的事情。 典型的Erlang系統(tǒng)具有成千上萬(wàn)的線程。 像我們?cè)贘ava中那樣,線程池和執(zhí)行器沒(méi)有麻煩。
從我所涉獵的內(nèi)容來(lái)看,我發(fā)現(xiàn)Erlang是功能語(yǔ)言與允許您編寫(xiě)實(shí)際應(yīng)用程序的語(yǔ)言之間的一種令人愉快的折衷。 (我知道我會(huì)為此感到遲疑)強(qiáng)大的分布式錯(cuò)誤處理令人驚喜,編寫(xiě)任何類型的網(wǎng)絡(luò)服務(wù)器實(shí)際上都很容易。 Web服務(wù)器的狀態(tài)機(jī)方法使回滾錯(cuò)誤變得完全自然。
但是這篇文章不是關(guān)于Erlang的編程模型的。 這是關(guān)于Erlang VM處理內(nèi)存的方式。
當(dāng)前的Java虛擬機(jī)使用Erlang程序員稱為共享堆拓?fù)涞臇|西。 所有線程都使用一個(gè)大堆。 大多數(shù)內(nèi)存分配在該堆上。 除了堆之外,JVM還使用一些專用數(shù)據(jù)區(qū)域,例如代碼緩存和永久生成。 這些也在所有線程之間共享。
相比之下, Erlang使用私有堆拓?fù)洹?每個(gè)線程都有自己的微小堆,該堆包含該線程使用的所有數(shù)據(jù)以及該線程的堆棧。 線程的所有數(shù)據(jù)都在該本地堆上。 創(chuàng)建線程時(shí)保留它。 當(dāng)線程死亡時(shí),整個(gè)堆將簡(jiǎn)單地返回到空閑內(nèi)存池。
除了私有堆之外,所有線程都共享對(duì)所謂的二進(jìn)制堆和消息堆的訪問(wèn)。 這些是專門(mén)的堆。 二進(jìn)制堆用于分配可能在線程之間共享的大塊任意數(shù)據(jù)。 例如,這是文件輸入或網(wǎng)絡(luò)緩沖區(qū)所在的位置。
消息堆是消息中使用的數(shù)據(jù)的堆。 消息也在進(jìn)程之間共享。 通過(guò)將指針從發(fā)送線程復(fù)制到接收線程,可以在線程之間傳遞消息。 消息的數(shù)據(jù)存儲(chǔ)在消息堆上。
Erlang內(nèi)存模型給我留下了深刻的印象。 它比Java的單堆模型具有更大的可擴(kuò)展性。 語(yǔ)言語(yǔ)義和內(nèi)存模型完美匹配。
例如; 堆是線程專用的一個(gè)簡(jiǎn)單事實(shí)可以減輕線程對(duì)自己數(shù)據(jù)的所有形式的鎖檢查的負(fù)擔(dān)。 除此之外,沒(méi)有破壞性的寫(xiě)操作,并且突然也不需要對(duì)共享數(shù)據(jù)進(jìn)行鎖定檢查。
最新版本的Erlang VM通過(guò)擁有多個(gè)調(diào)度程序,進(jìn)一步邁出了又一步。 確切地說(shuō),每個(gè)物理處理器一個(gè)調(diào)度程序。 這樣就消除了另一類要檢查的鎖。 僅在無(wú)聊的調(diào)度程序時(shí),它才需要出去,收集一個(gè)鎖,并從另一個(gè)調(diào)度程序中獲取一些進(jìn)程。
在Java中,我們還有很多東西要學(xué)習(xí)。 就是說(shuō),我們?cè)贘ava中有一些不錯(cuò)的東西,我錯(cuò)過(guò)了使用大型Erlang系統(tǒng)的情況。
當(dāng)線程累積大量數(shù)據(jù)時(shí), Erlang VM將重新分配并增加堆。 但是,重新分配算法導(dǎo)致堆大小快速增長(zhǎng)。 在高負(fù)載下,我們已經(jīng)看到Erlang VM在幾分鐘之內(nèi)吞噬了16GB的RAM。 每個(gè)發(fā)行版都必須經(jīng)過(guò)仔細(xì)的負(fù)載測(cè)試,以查看其內(nèi)存需求是否仍然合理。
Erlang VM中沒(méi)有任何機(jī)制可以抑制內(nèi)存的增長(zhǎng)。 VM會(huì)愉快地分配過(guò)多的內(nèi)存,以至于系統(tǒng)需要進(jìn)行交換,或者虛擬內(nèi)存已用完。 這些可能會(huì)導(dǎo)致機(jī)器甚至無(wú)法響應(yīng)KVM控制臺(tái)訪問(wèn)。 過(guò)去,我們不得不關(guān)閉機(jī)器并重新啟動(dòng),才能再次使用它們。
基于隊(duì)列的編程模型使Erlang為其編寫(xiě)代碼變得非常有趣,這也是生產(chǎn)中的致命弱點(diǎn)。 Erlang中的每個(gè)隊(duì)列都是無(wú)界的。 VM不會(huì)引發(fā)異常或限制隊(duì)列中的消息數(shù)。 有時(shí),進(jìn)程會(huì)由于錯(cuò)誤而停止處理,或者進(jìn)程無(wú)法跟上發(fā)送給它的消息流的速度。 在這種情況下, Erlang將只允許該進(jìn)程的隊(duì)列增加,直到VM被殺死或機(jī)器被鎖定(以先到者為準(zhǔn))。
這意味著,當(dāng)您在生產(chǎn)環(huán)境中運(yùn)行大型Erlang VM時(shí),您需要進(jìn)行OS級(jí)別的檢查,如果內(nèi)存使用過(guò)多的話,這些檢查將殺死進(jìn)程。 對(duì)于運(yùn)行大型Erlang VM的計(jì)算機(jī),必須具有計(jì)算機(jī)的遠(yuǎn)程控制權(quán)或遠(yuǎn)程訪問(wèn)卡。
總之,對(duì)于每天的性能,我相信私有堆內(nèi)存模型是Erlang盒子中非常強(qiáng)大的工具。 它將鎖定機(jī)制的所有類都排除在運(yùn)行時(shí)系統(tǒng)之外,這意味著在相同的目的下,它將比Java更好地?cái)U(kuò)展。 當(dāng)系統(tǒng)被洪水或DDoSed攻擊時(shí),Java對(duì)內(nèi)存的嚴(yán)格限制將節(jié)省您的培根。
最后的想法
Erlang的VM有一個(gè)命令行開(kāi)關(guān),可以將其從使用私有堆拓?fù)淝袚Q到使用共享堆拓?fù)洹?
我喜歡Erlang和Java。 它們之所以難以比較,是因?yàn)樗鼈兣c開(kāi)發(fā)人員的共同點(diǎn)很少。 通常,我會(huì)在大多數(shù)系統(tǒng)上使用Java。 工具支持更好,可用庫(kù)的數(shù)量驚人。 如果我有一個(gè)面向流的消息傳遞系統(tǒng),我會(huì)選擇Erlang 。 那時(shí), Erlang編程模型才真正發(fā)光。
參考文獻(xiàn):
- 我們的JCG合作伙伴Kees Jan Koster (來(lái)自Java-Monitor)的 Erlang內(nèi)存架構(gòu)與Java內(nèi)存架構(gòu)
編碼愉快! 不要忘記分享!
拜倫
相關(guān)文章:
- Java最佳實(shí)踐系列
- 正確記錄應(yīng)用程序的10個(gè)技巧
- 每個(gè)程序員都應(yīng)該知道的事情
- 生存在狂野西部開(kāi)發(fā)過(guò)程中的9條提示
- 軟件設(shè)計(jì)法則
- Java Fork / Join進(jìn)行并行編程
翻譯自: https://www.javacodegeeks.com/2011/04/erlang-vs-java-memory-architecture.html
總結(jié)
以上是生活随笔為你收集整理的Erlang与Java内存架构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 博世本周完成收购 TSI Semicon
- 下一篇: 人大金仓发布三款数据库新品 面向市场需求