Clojure: Multimethods vs Protocols

Let's measure how much multimethods are slower that protocols:

(defrecord Order [price])
;; protocol
(defprotocol Calculable
(p-total [this]))
(extend-protocol Calculable
Order
(p-total [order] (:price order))
clojure.lang.IPersistentMap
(p-total [m] (:price m)))
;; multimethod that accesses the object as a map
(defmulti m-map-total class)
(defmethod m-map-total Order [order] (:price order))
(defmethod m-map-total clojure.lang.IPersistentMap [m] (:price m))
;; multimethod that accesses the object as a class
(defmulti m-class-total class)
(defmethod m-class-total Order [order] (.price order))
;; test
(defn measure
[constructor type]
(let [orders (reduce conj (for [n (range 3000000)] (constructor n)) ())]
(prn (format "created %s %ss." (count orders) type))
(doseq [[f msg] [[:price "direct (map)"]
[p-total "protocol"]
[m-map-total "multimethod (map)"]
[#(.price %) "direct (class)"]
[m-class-total "multimethod (class)"]]]
(prn (format
"%s: %s msecs."
msg
(try
(tc (dorun (map f orders)))
(catch Exception ex (str ex))))))))
(measure #(Order. %) "order")
(measure #(hash-map :price %) "map")
; created 3000000 orders.
; direct (map): 261.759601 msecs.
; protocol: 227.293889 msecs.
; multimethod (map): 330.989975 msecs.
; direct (class): 6391.209907 msecs.
; multimethod (class): 6412.286282 msecs.
;
; created 3000000 maps.
; direct (map): 289.209819 msecs.
; protocol: 329.602042 msecs.
; multimethod (map): 645.605847 msecs.
; direct (class): -
; multimethod (class): -
view raw gistfile1.clj hosted with ❤ by GitHub

  • multimethods are roughly as fast as protocols
  • clojure maps as fast as records
  • "class" notation is in order of magnitude slower than "map" notation

Comments

daniil said…
> "class" notation is in order of magnitude slower than "map" notation

Isn't this because there is reflection involved when calling .price? Type-hinting the argument should solve this.

Popular posts from this blog

Regular expressions: Rust vs F# vs Scala

Hash maps: Rust, F#, D, Go, Scala

Haskell: performance