Skip to content

Instantly share code, notes, and snippets.

@moxaj
Last active August 23, 2016 13:09
Show Gist options
  • Save moxaj/bb9d34eb4eb92455ddc04e51394f48f9 to your computer and use it in GitHub Desktop.
Save moxaj/bb9d34eb4eb92455ddc04e51394f48f9 to your computer and use it in GitHub Desktop.
defprotocol vs definterface
(ns test
"Performance comparison between defprotocol and definterface
with primitive args and return values."
(:require [criterium.core :as c]))
(set! *warn-on-reflection* true)
(set! *unchecked-math* :warn-on-boxed)
(defn no-meta
{:inline (fn [arg] `(with-meta ~arg nil))}
[arg]
(with-meta arg nil))
(defmacro definterface+ [name cljs? & ops]
(let [ops (map (fn [[op-name args args' doc-string]]
(list op-name
args
(vec (cons 'this (map no-meta args)))
(if doc-string [doc-string] [])))
ops)
inner-form `(~(if cljs? `defprotocol `definterface)
~name
~@(map (fn [[op-name args args' doc-string]]
(if cljs?
`(~(no-meta op-name)
~args'
~@doc-string)
`(~(with-meta (munge op-name) (meta op-name))
~args
~@doc-string)))
ops))]
(if cljs?
inner-form
`(do ~inner-form
~@(map (fn [[op-name args args' doc-string]]
`(defn ~(no-meta op-name)
{:inline (fn ~args'
`(~'~(symbol (str "." (munge op-name)))
~~@args'))}
~(with-meta (vec (cons (with-meta 'this {:tag name})
args))
(meta op-name))
(~(symbol (str "." (munge op-name)))
~@args')))
ops)))))
(definterface+ I1 true
(^long bar1 [^long z]))
(definterface+ I2 false
(^long bar2 [^long z]))
(deftype A []
I1
(bar1 [this z] (+ z 20))
I2
(bar2 [this z] (+ z 20)))
(comment
(let [a (A.)]
(c/with-progress-reporting
(c/quick-bench
(+ 10 (bar1 a 30)))))
=> 24,669818 ns
(let [a (A.)]
(c/with-progress-reporting
(c/quick-bench
(+ 10 (bar2 a 30)))))
=> 4,549601 ns
nil)
@moxaj
Copy link
Author

moxaj commented Aug 23, 2016

long (un)boxing takes around ~5ns, the first case involves 4 (un)boxing operations, so it adds up nicely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment