2016-08-13 2 views
3

Я по отношению к новому Clojure и иметь следующую простую функциюClojure: Why = и .equals на строках имеют разную производительность?

(defn find-func 
[what seq] 
    (filter #(.equals what %) seq) 
) 

Я заметил, что данная функция значительно медленнее, чем когда я заменяю .equals с = как это:

(defn find-func 
[what seq] 
    (filter #(= what %) seq) 
) 

Я наблюдал это когда я побежал от РЕПЛ на JDK 1.8.0_25, Clojure 1.8:

(find-func "10" (map str (range 0 800000))) 

Почему это так? Я, однако, из другого ответа stackoverflow (Stack overflow question), который = вызывает .equals, так что не должно быть разницы в производительности. Это было оптимизировано с того времени? Спасибо за любые разъяснения.

+0

Скорее всего, очень связанный. Я только выяснил, что такое же различие производительности относится к (.endsWith what%) и (clojure.string.ends-with? What%) – Vojta

ответ

6

Проблема заключается в том, что ваша первая find-func использует отражение, в то время как ваш второй один не делает:

(set! *warn-on-reflection* true) 

(defn find-func [what seq] 
    (filter #(.equals what %) seq)) 
;; Reflection warning, foo.clj:2:12 - call to method equals can't be resolved (target class is unknown). 

(defn find-func [what seq] 
    (filter #(= what %) seq)) 

Если добавить тип подсказки, чтобы избежать отражения, .equals будет быстрее, чем =:

(defn find-func [^Object what seq] 
    (filter #(.equals what %) seq)) 

Clojure должен уметь вычислять это самостоятельно, но по какой-то причине это не так.

Смежные вопросы