Улучшения Clojure JVM 7/8

Рич Хикки и другие упомянули, что Clojure не получит значительного улучшения по сравнению с грядущим invokeDynamic, запланированным для JVM 7 или 8, но увидит прирост производительности за счет хвостовой рекурсии.

Повлияет ли хвостовая рекурсия на

(fn [...] (recur ...))

or

(loop [...] (recur ...))

Я не ожидаю, что они станут быстрее, поскольку компилятор, вероятно, уже генерирует структуры циклов.


person Ralph    schedule 29.11.2010    source источник


Ответы (1)


Не ваши примеры будут работать быстрее, потому что, если вы используете recur, вы уже сообщаете компилятору, что у вас есть хвостовая рекурсивная функция, и это позволяет компилятору генерировать байтовый код, который использует goto (как обычный императивный цикл)

Конечно, есть некоторые преимущества, если JVM получает оптимизацию хвостового вызова.

Вам больше не придется использовать recur (если вы этого не хотите), поэтому вы можете написать такую ​​​​функцию (хвостовая рекурсивная функция)

(defn testfn [n] (when (not= 1000 n) (testfn n)))

В настоящее время JVM не может обнаружить хвостовую рекурсию. С добавлением оптимизации хвостового вызова JVM может видеть приведенную выше функцию так же, как если бы вы написали это (и, следовательно, получить императивную скорость цикла):

(defn testfn [n] (when (not= 1000 n) (recur n)))

Так что это не такое уж большое улучшение, но есть еще один случай, когда оптимизация хвостового вызова действительно великолепна.

Если у вас есть функции, которые вызывают друг друга (иногда даже больше двух), и им не нужно удерживать стек (являются хвостовой рекурсией), JVM может их оптимизировать. Сейчас это невозможно, потому что вы не можете указать recur перейти к какой-либо другой функции. Вот пример.

(defn even [n] (if (zero? n) true (odd? (dec n)))
(defn odd  [n] (if (zero? n) false (even (dec n)))

Если вы попробуете это с большим числом, знайте, что вы взорвете стек, но с оптимизацией хвостового вызова вы этого не сделаете.

У меня осталось немного прибавления. Существует функция под названием trampoline, которая позволяет вам сделать это уже (с небольшим изменением стиля программирования и некоторыми накладными расходами). Вместо объяснения trampoline я отсылаю вас к блогу, который делает именно это:

http://pramode.net/clojure/2010/05/08/clojure-trampoline/

person nickik    schedule 29.11.2010