-
-
Save GR-John/6eed1ba1a9b823f402fd16439860beb9 to your computer and use it in GitHub Desktop.
Idiomatically refactor Clojure code to improve performance
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; 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