フォローこの質問で約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をルートvarまたはletにバインドすることで確認できます。
=> (let [f aget] (time (reduce + (for [x xa] (f xa x)))))
"Elapsed time: 43.912129 msecs"
4999950000
バウンドAGETは、コア機能がない場合には、最適化する方法を「知っている」ように見える理由を任意のアイデア?
clojureコンパイラがすべてのオブジェクトを使用する理由、パフォーマンスがタイプヒントバージョンとほとんど同じで、タイプヒントが与えられていない最悪の場合のパフォーマンスバージョンではないのは分かりますか? – NielsK
JVMのHotSpotコンパイラは、(私にとっては)奇妙なこととオブジェクトを使ったすばらしいことを行います...最悪の場合は、クラス内のすべての関数を名前で見つけて、少なくとも回避することです。 –
私はパラメータとして渡された関数を呼び出すことについてのみ話しています。最適化画像は、呼び出されている関数がコンパイル時に固定されている場合(「通常の」場合) –