Followup по этому вопросу о 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
Компилятор HotSpot в JVM делает странные (для меня) и замечательные вещи с объектами ... Худший случай - это отразить, чтобы найти каждую функцию по имени в своем классе, по крайней мере, вы избегаете этого :) –
Я только говоря о вызове функции, которая была передана как параметр. оптимизация изображения лучше в тех случаях, когда вызываемая функция фиксируется во время компиляции («нормальный» случай) –