Skip to content

Instantly share code, notes, and snippets.

@tonsky
Last active December 3, 2016 08:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tonsky/442eda3ba6aa4a71fd67883bb3f61d99 to your computer and use it in GitHub Desktop.
Save tonsky/442eda3ba6aa4a71fd67883bb3f61d99 to your computer and use it in GitHub Desktop.
(require '[criterium.core :as c])
(defn new_=
"Equality. Returns true if x equals y, false if not. Same as
Java x.equals(y) except it also works for nil, and compares
numbers and collections in a type-independent manner. Clojure's immutable data
structures define equals() (and thus =) as a value, not an identity,
comparison."
{:inline (fn [x y] `(. clojure.lang.Util equiv ~x ~y))
:inline-arities #{2}
:added "1.0"}
([x] true)
([x y] (clojure.lang.Util/equiv x y))
([x y z] (and (clojure.lang.Util/equiv x y)
(clojure.lang.Util/equiv y z)))
([x y z & more]
(if (clojure.lang.Util/equiv x y)
(let [nmore (next more)]
(if nmore
(recur y z (first more) nmore)
(new_= y z (first more))))
false)))
(defn new_not=
"Same as (not (= obj1 obj2))"
{:tag Boolean
:added "1.0"
:static true}
([x] false)
([x y] (not (new_= x y)))
([x y z] (not (new_= x y z)))
([x y z & more]
(if (new_= x y)
(let [nmore (next more)]
(if nmore
(recur y z (first more) nmore)
(new_not= y z (first more))))
true)))
(defn new_<
"Returns non-nil if nums are in monotonically increasing order,
otherwise false."
{:inline (fn [x y] `(. clojure.lang.Numbers (lt ~x ~y)))
:inline-arities #{2}
:added "1.0"}
([x] true)
([x y] (. clojure.lang.Numbers (lt x y)))
([x y z] (and (. clojure.lang.Numbers (lt x y))
(. clojure.lang.Numbers (lt y z))))
([x y z & more]
(if (new_< x y)
(let [nmore (next more)]
(if nmore
(recur y z (first more) nmore)
(new_< y z (first more))))
false)))
(defn new_<=
"Returns non-nil if nums are in monotonically non-decreasing order,
otherwise false."
{:inline (fn [x y] `(. clojure.lang.Numbers (lte ~x ~y)))
:inline-arities #{2}
:added "1.0"}
([x] true)
([x y] (. clojure.lang.Numbers (lte x y)))
([x y z] (and (. clojure.lang.Numbers (lte x y))
(. clojure.lang.Numbers (lte y z))))
([x y z & more]
(if (new_<= x y)
(let [nmore (next more)]
(if nmore
(recur y z (first more) nmore)
(new_<= y z (first more))))
false)))
(defn new_>
"Returns non-nil if nums are in monotonically decreasing order,
otherwise false."
{:inline (fn [x y] `(. clojure.lang.Numbers (gt ~x ~y)))
:inline-arities #{2}
:added "1.0"}
([x] true)
([x y] (. clojure.lang.Numbers (gt x y)))
([x y z] (and (. clojure.lang.Numbers (gt x y))
(. clojure.lang.Numbers (gt y z))))
([x y z & more]
(if (new_> x y)
(let [nmore (next more)]
(if nmore
(recur y z (first more) nmore)
(new_> y z (first more))))
false)))
(defn new_>=
"Returns non-nil if nums are in monotonically non-increasing order,
otherwise false."
{:inline (fn [x y] `(. clojure.lang.Numbers (gte ~x ~y)))
:inline-arities #{2}
:added "1.0"}
([x] true)
([x y] (. clojure.lang.Numbers (gte x y)))
([x y z] (and (. clojure.lang.Numbers (gte x y))
(. clojure.lang.Numbers (gte y z))))
([x y z & more]
(if (new_>= x y)
(let [nmore (next more)]
(if nmore
(recur y z (first more) nmore)
(new_>= y z (first more))))
false)))
(defn new_==
"Returns non-nil if nums all have the equivalent
value (type-independent), otherwise false"
{:inline (fn [x y] `(. clojure.lang.Numbers (equiv ~x ~y)))
:inline-arities #{2}
:added "1.0"}
([x] true)
([x y] (. clojure.lang.Numbers (equiv x y)))
([x y z] (and (. clojure.lang.Numbers (equiv x y))
(. clojure.lang.Numbers (equiv y z))))
([x y z & more]
(if (new_== x y)
(let [nmore (next more)]
(if nmore
(recur y z (first more) nmore)
(new_== y z (first more))))
false)))
(defn format-time [estimate]
(let [mean (first estimate)
[factor unit] (c/scale-time mean)]
(c/format-value mean factor unit)))
(defmacro race [body1 body2]
`(let [results1# (c/quick-benchmark ~body1 {})
results2# (c/quick-benchmark ~body2 {})
percent# (->> (/ (first (:mean results2#))
(first (:mean results1#)))
(* 100)
(- 100)
(int))]
(println ~(pr-str body1) "\t"
(format-time (:mean results1#)) "=>" (format-time (:mean results2#))
(str "(-" percent# "%)"))))
(race (= 5 5 5) (new_= 5 5 5))
(race (= 5 5 5 5) (new_= 5 5 5 5))
(race (not= 1 2 3) (new_not= 1 2 3))
(race (not= 1 2 3 4) (new_not= 1 2 3 4))
(race (< 1 2 3) (new_< 1 2 3))
(race (< 1 2 3 4) (new_< 1 2 3 4))
(race (<= 1 2 2) (new_<= 1 2 2))
(race (<= 1 2 2 4) (new_<= 1 2 2 4))
(race (> 3 2 1) (new_> 3 2 1))
(race (> 3 2 1 0) (new_> 3 2 1 0))
(race (>= 3 2 2) (new_>= 3 2 2))
(race (>= 3 2 2 0) (new_>= 3 2 2 0))
(race (== 5 5 5) (new_== 5 5 5))
(race (== 5 5 5 5) (new_== 5 5 5 5))
# Three-arities
(= 5 5 5) 24.508635 ns => 4.802783 ns (-80%)
(not= 1 2 3) 122.085793 ns => 21.828776 ns (-82%)
(< 1 2 3) 30.842993 ns => 6.714757 ns (-78%)
(<= 1 2 2) 30.712399 ns => 6.011326 ns (-80%)
(> 3 2 1) 22.577751 ns => 6.893885 ns (-69%)
(>= 3 2 2) 21.593219 ns => 6.233540 ns (-71%)
(== 5 5 5) 19.700540 ns => 6.066265 ns (-69%)
# Four-arities (vararg branch)
(= 5 5 5 5) 50.264580 ns => 31.361655 ns (-37%)
(not= 1 2 3 4) 130.517439 ns => 29.675640 ns (-77%)
(< 1 2 3 4) 68.059758 ns => 43.684409 ns (-35%)
(<= 1 2 2 4) 65.653826 ns => 45.194730 ns (-31%)
(> 3 2 1 0) 119.239733 ns => 44.305519 ns (-62%)
(>= 3 2 2 0) 65.738453 ns => 44.037442 ns (-33%)
(== 5 5 5 5) 50.773521 ns => 33.725097 ns (-33%)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment