Skip to content

Instantly share code, notes, and snippets.

@GR-John
Forked from bsless/slide-perf.clj
Created October 5, 2021 05:40
Show Gist options
  • Save GR-John/6eed1ba1a9b823f402fd16439860beb9 to your computer and use it in GitHub Desktop.
Save GR-John/6eed1ba1a9b823f402fd16439860beb9 to your computer and use it in GitHub Desktop.
Idiomatically refactor Clojure code to improve performance
;; http://johnj.com/from-elegance-to-speed.html
(def times (iterate #(+ % (rand-int 1000)) 0))
(def times-v (into [] (take 1e6) (iterate #(+ % (rand-int 1000)) 0)))
(defn smt-8 [times]
(->> times
(partition 8 1)
(map (juxt identity
(comp (partial apply -)
(juxt last first))))
(filter (comp (partial > 1000) second))
doall))
(cc/quick-bench (smt-8 times-v))
(defn sliding
([^long n]
(sliding n 1))
([^long n ^long step]
(fn [rf]
(let [a (java.util.ArrayDeque. n)]
(fn
([] (rf))
([result]
(let [result (if (.isEmpty a)
result
(let [v (vec (.toArray a))]
;;clear first!
(.clear a)
(unreduced (rf result v))))]
(rf result)))
([result input]
(.add a input)
(if (= n (.size a))
(let [v (clojure.lang.LazilyPersistentVector/createOwning (.toArray a))]
(dotimes [_ step] (.removeFirst a))
(rf result v))
result)))))))
(def smt-xf0
(comp
(sliding 8 1)
(map (juxt identity
(comp (partial apply -)
(juxt last first))))
(filter (comp (partial > 1000) second))))
(cc/quick-bench (doall (sequence smt-xf0 times-v)))
(def smt-xf1
(comp
(sliding 8 1)
(map (fn [v] [v (- (peek v) (nth v 0))]))
(filter (fn [v] (> 1000 (nth v 1))))))
(cc/quick-bench (doall (sequence smt-xf1 times-v)))
(def smt-xf2
(comp
(sliding 8 1)
(keep (fn [v] (let [d (- (peek v) (nth v 0))]
(when (> 1000 d)
[v d]))))))
(cc/quick-bench (doall (sequence smt-xf2 times-v)))
(import 'java.util.ArrayDeque)
(defn sliding*
([^long n]
(sliding* n 1))
([^long n ^long step]
(fn [rf]
(let [a (ArrayDeque. n)]
(fn
([] (rf))
([result]
(let [result (if (.isEmpty a)
result
(let [v (.toArray ^ArrayDeque a)]
;;clear first!
(.clear a)
(unreduced (rf result v))))]
(rf result)))
([result input]
(.add a input)
(if (= n (.size a))
(let [v (.toArray ^ArrayDeque a)]
(dotimes [_ step] (.removeFirst a))
(rf result v))
result)))))))
(def smt-xf3
(comp
(sliding* 8 1)
(keep (fn [^objects arr]
(let [d (- ^long (aget arr (unchecked-dec-int (alength arr))) ^long (aget arr 0))]
(when (> 1000 d)
[arr d]))))))
(do
(cc/quick-bench (smt-8 times-v)) ;; 1.2 sec
(cc/quick-bench (doall (sequence smt-xf0 times-v))) ;; 470 ms
(cc/quick-bench (doall (sequence smt-xf1 times-v))) ;; 54 ms
(cc/quick-bench (doall (sequence smt-xf2 times-v))) ;; 49 ms
(cc/quick-bench (doall (sequence smt-xf3 times-v))));; 30 ms
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment