Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are clojure multimethods slow by nature

I was looking at the clojure.core function re-groups:

(defn re-groups [^java.util.regex.Matcher m]
    (let [gc  (. m (groupCount))]
      (if (zero? gc)
        (. m (group))
        (loop [ret [] c 0]
          (if (<= c gc)
            (recur (conj ret (. m (group c))) (inc c))
             ret))))) 

And thought that it would be "better" to rewrite it as a multimethod:

(defmulti re-groups (fn [^java.util.regex.Matcher m] (.groupCount m)))
(defmethod re-groups 0 [m] (.group m))
(defmethod re-groups :default [m]
        (let [idxs (range (inc (.groupCount m)))]
             (reduce #(conj %1 (.group m %2)) [] idxs))) 

Yet when comparing the times I was surpised to see the rewrite is 4 times slower:

clojure.core: "Elapsed time: 668.029589 msecs"
multi-method: "Elapsed time: 2632.672379 msecs" 

Is this a natural result of multimethods or is there something else wrong here?

like image 568
M Smith Avatar asked Aug 31 '11 17:08

M Smith


2 Answers

Clojure multimethods allow runtime polymorphic behavior based on arbitrary dispatch functions. This is very powerful for building ad-hoc hierarchies and abstractions, but you pay a performance hit for such flexibility. You may wish to re-implement your solution with a protocol. Only use multimethods when you need complete runtime type flexibility.

like image 185
Julien Chastang Avatar answered Sep 22 '22 03:09

Julien Chastang


in general anything that does more will take more time. because multimethods offer a variety of ways to dispatch they will take longer than protocols you I have to answer your question "yes, when compared to protocols".

In practice start with protocols and go to multimethods when you have to (and it looks like you need them). you can't make the computer faster with code, but you can make it do less

like image 33
Arthur Ulfeldt Avatar answered Sep 26 '22 03:09

Arthur Ulfeldt