關於這個問題的後續關於aget performance奇怪的aget優化行爲
似乎有什麼東西很奇怪進行優化明智。我們知道下面是真實的:
=> (def xa (int-array (range 100000)))
#'user/xa
=> (set! *warn-on-reflection* true)
true
=> (time (reduce + (for [x xa] (aget ^ints xa x))))
"Elapsed time: 42.80174 msecs"
4999950000
=> (time (reduce + (for [x xa] (aget xa x))))
"Elapsed time: 2067.673859 msecs"
4999950000
Reflection warning, NO_SOURCE_PATH:1 - call to aget can't be resolved.
Reflection warning, NO_SOURCE_PATH:1 - call to aget can't be resolved.
然而,另外一些實驗確實weirded我出去:
=> (for [f [get nth aget]] (time (reduce + (for [x xa] (f xa x)))))
("Elapsed time: 71.898128 msecs"
"Elapsed time: 62.080851 msecs"
"Elapsed time: 46.721892 msecs"
4999950000 4999950000 4999950000)
無反射的警告,沒有必要提示。通過將aget綁定到根變量或let中可以看到相同的行爲。
=> (let [f aget] (time (reduce + (for [x xa] (f xa x)))))
"Elapsed time: 43.912129 msecs"
4999950000
任何想法爲什麼一個約束的aget似乎'知道'如何優化,其中的核心功能不?
我不明白的是,如果clojure編譯器爲所有東西使用對象,爲什麼性能幾乎與類型提示版本相同,而不是沒有給出類型提示的最差情況性能版本? – NielsK 2012-04-13 17:46:21
JVM中的HotSpot編譯器對於對象來說很奇怪(對我來說)和奇妙的事物......最糟糕的情況是不得不反思在類中找到每個函數的名字,至少你是在避免那個:) – 2012-04-13 17:49:54
我是隻討論調用作爲參數傳遞的函數。在被調用的函數在編譯時固定的情況下(「正常」情況),優化圖片更好, – 2012-04-13 17:56:52