2012-12-11 21 views
16

如果我不得不猜測,我很確定答案是Clojure,但我不知道爲什麼。邏輯上(對我來說)好像ClojureScript應該會更快:哪個更快,Clojure或ClojureScript(以及爲什麼)?

兩者都是「動態」,但ClojureScript

  • 編譯成JavaScript,在V8上運行
  • V8發動機可以說是最快的動態語言引擎有
  • V8是用C

而Clojure的:

  • 也是動態的JVM,它沒有內置的動態支持
  • 上運行,所以我想這樣JVM有做任何V8做得太過,以實現動態支持
  • 和Java是慢C

那麼Clojure怎麼會比ClojureScript更快呢?說動態JavaScript和Clojure是動態的時,「動態」意味着什麼不同?我沒有看到什麼?

(當然,如果ClojureScript 確實快,然後是上面的推理是否正確?)

我想,這是什麼的Clojure編譯成....是問題的至少一部分。我知道JVM部分不能只是一個簡單的解釋器(否則ClojureScript會更快),但Clojure無法編譯爲常規字節碼,因爲JVM中沒有「動態」部分。那麼編譯/執行ClojureScript的方式和編譯/執行Clojure的方式以及編譯/執行Java的方式有什麼區別,以及每種方式所隱含的性能差異?

+5

「Java比C慢」可能適用於許多問題領域,但無關緊要。適當的問題是「Java比V8慢」。 V8不會將你的代碼作爲編譯後的C代碼運行,它恰好是用C編寫的JavaScript解釋器。 –

+0

@EricJ。我想這就是我的問題,我看到V8解釋了Clojure生成的JavaScript與解釋Clojure的JVM。 V8將JS編譯成機器代碼並運行它。 JVM做的更快嗎? – lobsterism

+1

Clojure被編譯爲字節碼,就像Java一樣。是什麼讓你覺得它不是? –

回答

24

這個問題很難準確地回答,沒有提及特定的基準測試任務(或者甚至是特定版本的Clojure或ClojureScript)。

話雖如此,在大多數情況下,我會希望Clojure稍微快一點。原因:

  • Clojure的通常編譯成靜態代碼,因此它實際上並沒有在運行時做任何動態查詢。這非常重要:高性能代碼通常會產生與靜態類型化的Java非常相似的字節碼。這個問題似乎在假設動態語言必須在運行時進行動態方法查找:這並非總是如此(並且通常不在Clojure中)
  • JVM JIT的設計非常好,而且我相信儘管V8有多出色,但它仍然比JavaScript JIT好一些。
  • 如果您需要併發性或需要利用多核心,那麼顯然沒有比賽,因爲JavaScript是單線程的......
  • Clojure編譯器比ClojureScript更成熟,並且有相當多的近年來的性能調整工作(包括原始支持,協議等)

當然,可以用任何語言編寫快速或慢速的代碼。這將比語言實現之間的根本區別更有區別。

更基本的是,你在Clojure和ClojureScript之間的選擇不應該是關於任何情況下的性能。兩者都提供了極具生產力的優勢主要的決定因素應該是:

  • 如果你想在網絡上運行,如果你想在一個JVM environnment運行在服務器上使用ClojureScript
  • ,使用Clojure的
+0

好的,我認爲你的第一點是我的困惑之源。所以你說如果有人「濫用」動態的東西,並且運行時一直在做動態查找,那麼誰知道哪個更快,但99%的時間並不是這種情況,字節碼在那裏跳動解釋代碼,對?你有什麼想法%性能差異會是什麼?我猜如果純粹的執行是瓶頸,那麼它與JS vs Java的差異是相同的? – lobsterism

+2

是的Java與JavaScript可能會給出優化的Clojure與優化的ClojureScript之間的大致差異百分比。畢竟,各自的平臺是限制因素......從長遠來看,您可以預期Clojure傾向於Java性能,ClojureScript傾向於JavaScript性能,因爲編譯器越來越好。 – mikera

28

實際上,V8是用C++編寫的。然而,與JVM基本上是一樣的,而JVM是用C.V8 JITs編寫的Javascript代碼並執行JIT代碼。同樣,JVM JIT編譯(或熱點編譯)字節碼(不是J​​ava)並執行生成的代碼。

Bytecode不是靜態的,就像Java一樣。事實上它可以是相當動態的。另一方面,Java大多是靜態的,將Java與字節碼混淆是不正確的。 java編譯器將Java源代碼轉換爲字節碼,JVM執行字節碼。欲瞭解更多信息,我建議你看看John Rose的博客(example)。那裏有很多很好的信息。另外,請嘗試通過Cliff Click尋找對話(如)。

同樣,Clojure代碼直接編譯爲字節碼,然後JVM對該字節碼執行相同的過程。編譯Clojure通常在運行時完成,這不是最快的過程。同樣,將Clojurescript翻譯成Javascript也不是很快。 V8的Javascript轉換爲可執行形式顯然是相當快的。雖然Clojure可以提前編譯爲字節碼,並且可以消除大量啓動開銷。

正如你所說,說JVM解釋字節碼也是不正確的。 1.0版本在17年前就已經這樣做了!

傳統上,有兩種編譯模式。第一種模式是JIT(Just in Time)編譯器。字節碼直接轉換爲機器碼。Java的JIT編譯執行速度很快,並且不會生成高度優化的代碼。它運行正常。

第二種模式稱爲熱點編譯器。熱點編譯器非常複雜。它在解釋模式下非常快速地啓動程序,並在程序運行時對其進行分析。當它檢測到熱點(頻繁執行的代碼中的點)時,它會編譯這些熱點。而JIT編譯器必須是快速的,因爲除非被JIT處理,否則什麼都不執行,熱點編譯器可以花費額外的時間來優化它正在編譯的代碼。

此外,它可以返回並重新訪問該代碼,並在必要和可能的情況下對其應用更多優化。這是熱點編譯器可以開始擊敗已編譯的C/C++的關鍵。由於它具有代碼的運行時知識,因此可以應用靜態C/C++編譯器無法完成的優化。例如,它可以內聯虛擬功能。

熱點還有一個其他功能,盡我所知沒有其他環境,它也可以去代碼,如果有必要。例如,如果代碼持續採用單個分支,並且該代碼已經過優化,並且運行時條件發生變化,則代碼會強制其他(未優化的)分支,並且性能突然變得糟糕。熱點可以對該功能進行優化,並再次開始分析以找出如何使其運行得更好。

熱點的缺點是開始有點慢。 Java 7 JVM的一個變化是將JIT編譯器和熱點編譯器結合起來。儘管這種模式是新的,但它並不是默認的,但是一旦初始啓動應該是好的,然後它可以開始JVM擅長的advanced optimizations

乾杯!

+0

謝謝,我實際上不知道JVM支持的動態。谷歌搜索,雖然我偶然發現http://blog.fogus.me/2011/10/14/why-clojure-doesnt-need-invokedynamic-but-it-might-be-nice,這表明Clojure並沒有實際上甚至利用該功能,但也幫助我理解爲什麼它仍然可以很快。 – lobsterism

+0

如果您從去年開始觀看Rich Hickey的Clojure Conj主題演講,他會談論對該功能的支持。這會很好,但是舊的JVM會出現問題。 – Bill

+1

此外,我忘了添加您的問題的實際答案。這取決於。 ;-) – Bill

1

這是與其說是歷史評論,不如說是答案:HotSpot虛擬機和V8 js引擎都可以追溯到Sun Microsystems的Self項目,我認爲它的原型有許多技術,可以讓它們以最快的速度運行做。比較兩者時需要考慮的事項。我會發布這個評論,但聲譽系統阻止了我。

相關問題