Loop:緊湊的JVM多核語(yǔ)言
作為一種緊湊簡(jiǎn)潔的JVM編程語(yǔ)言,Loop很明顯地受到了Haskell、Scheme、Ruby和Erlang的影響,而且它也同時(shí)嘗試著將函數(shù)式語(yǔ)言和面向?qū)ο笳Z(yǔ)言的優(yōu)秀特性實(shí)用且一致地整合在一起。
程序會(huì)在傳輸?shù)絁VM中進(jìn)行編譯,而且會(huì)盡可能地優(yōu)化,這樣在解釋執(zhí)行的時(shí)候就不會(huì)產(chǎn)生性能損失;所有的這一切優(yōu)化都是為了產(chǎn)生高效的可執(zhí)行代碼。
Loop的源碼文件結(jié)構(gòu)一般如下:
- module declaration
- import declarations
- functions & type definitions
- free expressions
下面是一個(gè)Loop程序的例子:
- module mymodule
- require othermod
- require yet.another
- class Pair ->
- left: 0
- right: 0
- main ->
- new Pair() # 注釋可以放在任何地方
- #自由表達(dá)式必須放在最后
- print('mymodule is go!')
InfoQ和Loop的創(chuàng)建者Dhanji R. Prasanna進(jìn)行了一次小型的問(wèn)答互動(dòng),在這之前,有必要對(duì)Dhanji做一下介紹,他是前Google工程師,JAX-RS規(guī)范的作者之一,“依賴注入:設(shè)計(jì)模式”的作者,Manning出版社已經(jīng)將這本書付梓。
InfoQ:Loop相比其他的JVM語(yǔ)言來(lái)說(shuō)有何不同?
Dhanji:我不想做一個(gè)面面俱到的特性比較,不過(guò)我覺(jué)得,若是闡述Loop的設(shè)計(jì)理念,這將能更好地回答你的這個(gè)問(wèn)題,Loop是為了讓開發(fā)者有一個(gè)一致、簡(jiǎn)單而且快樂(lè)的編程經(jīng)歷。所有的特性都是經(jīng)過(guò)精心設(shè)計(jì),并且設(shè)計(jì)過(guò)程中我非常仔細(xì)地考慮了特性之間的交互,不僅僅是句法上,而且還包括了語(yǔ)義。在其他的語(yǔ)言中,你可能有很多方法來(lái)完成一件事情,這已經(jīng)幾乎成為一種語(yǔ)言的特性,但是我覺(jué)得,多數(shù)其他實(shí)現(xiàn)都是不需要的。在Loop中,我嘗試著對(duì)如何完成一件事情做出種種限制,這樣便能夠保持語(yǔ)言的簡(jiǎn)潔和簡(jiǎn)單,從而得到一個(gè)富有魅力的,感覺(jué)舒適的語(yǔ)法。要知道,閱讀和編寫代碼應(yīng)該是一個(gè)簡(jiǎn)單愉快的過(guò)程。
另外一個(gè)區(qū)別就是Loop源代碼直接編譯成為JVM字節(jié)碼,但是這個(gè)編譯過(guò)程是在傳送到JVM的過(guò)程中完成。也就是說(shuō)它看起來(lái)非常像是一門腳本語(yǔ)言(而且像Lisp一樣是REPL(讀取,求值,打印,循環(huán))式),但是它的性能實(shí)際上要比真正的解釋型語(yǔ)言要好。我可以讓其他人做基準(zhǔn)測(cè)試來(lái)驗(yàn)證,不過(guò)現(xiàn)在看來(lái),在我做的簡(jiǎn)單測(cè)試中,Loop的速度非常快。我也在啟動(dòng)優(yōu)化上花費(fèi)了很多時(shí)間和精力,因此它的啟動(dòng)速度能夠完全達(dá)到JVM的極限,我可以毫不夸張的說(shuō),啟動(dòng)速度這個(gè)特性通常被大多數(shù)JVM語(yǔ)言給忽略了。
Loop也是緊密地和Java結(jié)合在一起。在Loop程序中可以很方便地調(diào)用Java方法或者使用Java對(duì)象。Lists、Sets和Maps都只是java.util的成員,但是做了一些擴(kuò)展(也簡(jiǎn)單地?cái)U(kuò)展了String)。這和其他的語(yǔ)言有區(qū)別,它們是維護(hù)了了兩個(gè)不同的庫(kù)來(lái)對(duì)Java庫(kù)進(jìn)行擴(kuò)展。
最后,Loop從一開始就內(nèi)建了對(duì)并發(fā)的支持,而且將不可變和狀態(tài)的共享作為不可或缺的特性。
InfoQ:你提到了許多Loop的特性都受到了例如Haskell、Scheme和Ruby這樣的語(yǔ)言的影響,你可以簡(jiǎn)單介紹一些例子嗎?
Dhanji:當(dāng)然,不過(guò)要知道,當(dāng)你說(shuō)“受到影響”的時(shí)候,人們總是趨向于認(rèn)為“直接抄襲”,并且會(huì)仔細(xì)地檢查你是不是有什么地方抄錯(cuò)了,應(yīng)付這種想法是非常艱難的。從我看來(lái),直接受到影響的部分是語(yǔ)法。尤其是Haskell的模式匹配,以及“where”和“do”語(yǔ)句塊,Scheme的類型系統(tǒng)、模塊,TCO(尾調(diào)用優(yōu)化)以及詞法結(jié)構(gòu)(閉包),當(dāng)然還有Ruby的符號(hào)以及自由形式的腳本。
這里有一個(gè)句法結(jié)構(gòu)的典型例子,你可以看到Loop是如何受到這些影響的,看看函數(shù)調(diào)用可以以一種后綴的形式來(lái)使用:
- print(36)
- # 可以寫為:
- 36.print()
這看起來(lái)的確很像是Ruby的函數(shù)調(diào)用,但是事實(shí)上,這是多態(tài)(重載)的函數(shù)的簡(jiǎn)單使用。我發(fā)現(xiàn)這種形式能夠增強(qiáng)某些代碼的可讀性,尤其是“擴(kuò)展”已經(jīng)存在的Java對(duì)象時(shí)候。當(dāng)然,我們也要權(quán)衡這種調(diào)用的利弊,不過(guò)我相信當(dāng)Loop成熟之時(shí),這個(gè)特性將會(huì)得到大量應(yīng)用。
更進(jìn)一步地說(shuō),Loop也還在函數(shù)設(shè)計(jì)的過(guò)程中受到了來(lái)自于Haskell和Scheme(尤其是后者)的語(yǔ)義影響。一個(gè)典型的例子便是從狀態(tài)性,面向封裝的設(shè)計(jì)轉(zhuǎn)為一個(gè)無(wú)狀態(tài),聲明式的設(shè)計(jì)。像Scheme,Loop在IO的設(shè)計(jì)上也并不是非常優(yōu)秀,但是另一方面來(lái)看,這也加強(qiáng)了并發(fā)程序的不可變性。這個(gè)加強(qiáng)之處很明顯地受到了Haskell哲學(xué)的影響。
不僅如此,Haskell還影響了如何將聲明式的代碼更易編寫和閱讀上。我非常喜歡這個(gè)哲學(xué)理念:代碼應(yīng)該讀起來(lái)像是一個(gè)解,而不是像一個(gè)如何在洗衣房洗衣的說(shuō)明列表;或者說(shuō),我們應(yīng)該強(qiáng)調(diào)程序“做什么”而不是“怎么樣”,Loop毫無(wú)疑問(wèn)地受到了這種理念的影響。
InfoQ:看起來(lái)Loop也花費(fèi)了非常多的精力在并發(fā)支持和內(nèi)建的消息傳遞接口上。你可以跟我們解釋一下和其他流行的并發(fā)技術(shù),Loop的并發(fā)支持有什么不同嗎?
Dhanji:這是一個(gè)非常好的問(wèn)題。Erlang有許多非常優(yōu)秀的地方值得借鑒。在Loop中實(shí)現(xiàn)并發(fā)有兩個(gè)主要的方法,它們都是Loop原生支持,而且,如果能夠相互結(jié)合使用將會(huì)非常強(qiáng)大:
消息驅(qū)動(dòng)通道(對(duì)消息傳遞,隊(duì)列和線程池的面向事件的抽象)
軟件事務(wù)內(nèi)存(一個(gè)用于共享可變狀態(tài)的無(wú)鎖的,原子性的一致性的模式)
前者將會(huì)管理好所有的細(xì)節(jié),你所面臨的只是一個(gè)抽象的概念。設(shè)置好可以并發(fā)執(zhí)行的輕量級(jí)的“通道”數(shù)目,然后簡(jiǎn)單地放入一堆任務(wù)即可,當(dāng)然也可以考慮將這些任務(wù)分片然后在各個(gè)片內(nèi),然后串行執(zhí)行。這其實(shí)提供了一個(gè)非常簡(jiǎn)單的方法來(lái)創(chuàng)建真正地分片事件隊(duì)列。因?yàn)橥ǖ朗欠浅5妮p量級(jí),你可以很簡(jiǎn)單很容易地創(chuàng)建成千上萬(wàn)的通道,然后用來(lái)分片執(zhí)行,例如,按照用戶名分片。每個(gè)串行通道各自擁有一小塊永久的內(nèi)存,這將會(huì)使得增量式任務(wù)處理更加容易。
Loop同樣保證每個(gè)線程都是平均分布在這些通道中,這個(gè)所謂的公平參數(shù)是可以配置的。所有我現(xiàn)在介紹的特性你現(xiàn)在可以馬上在Loop中找到,而且,以后每個(gè)串行通道將會(huì)有一個(gè)可以配置的線程池。
我提到了,串行通道擁有少量的永久私有內(nèi)存 - 另一方面,事務(wù)內(nèi)存則是一個(gè)更強(qiáng)大的選擇,如果你熟悉數(shù)據(jù)庫(kù)的話,Loop如何使用這個(gè)技術(shù)是和數(shù)據(jù)庫(kù)中的“并發(fā)優(yōu)化”類似。我們?cè)僖膊恍枰i這個(gè)概念,即便是在寫入的時(shí)候。這類內(nèi)存的優(yōu)化目標(biāo)便是超高吞吐量的讀操作和無(wú)阻塞的寫操作。這個(gè)已經(jīng)成為語(yǔ)法的一部分:
- update(person) in @person ->
- this.name: person.name,
- this.age: person.age
注意“in @person”,Loop將會(huì)在@person片中執(zhí)行這個(gè)事務(wù)
在這個(gè)方法中,我將會(huì)更新@person“事務(wù)片”中的數(shù)據(jù)。“this”指針指向當(dāng)前的事務(wù)片。當(dāng)函數(shù)完成的時(shí)候,當(dāng)前事務(wù)片將會(huì)對(duì)其他線程原子可見,或者失敗之后當(dāng)做完全沒(méi)有執(zhí)行過(guò)(類似于回滾)。其他的線程(即使不在這個(gè)事務(wù)中)都可以看到一個(gè)一致的@person片,然后這個(gè)片在事務(wù)執(zhí)行的時(shí)候會(huì)短暫不可見,所有的線程在事務(wù)完成之后將會(huì)馬上看到一個(gè)新的對(duì)象,無(wú)鎖,無(wú)需等待。這最激動(dòng)人心的事情便是讀和寫線程完全無(wú)阻塞。
這個(gè)特性仍然還是處于Alpha階段,我嘗試著搞定這個(gè)語(yǔ)義問(wèn)題,但是我真的覺(jué)得通道API使得Loop中并行編程變得優(yōu)美,強(qiáng)大而且容易理解。
你也可以在Github上提交你的代碼為Loop做貢獻(xiàn)。
原文鏈接:http://www.linuxeden.com/html/develop/20120716/127402.html
【編輯推薦】