Skip to content

Instantly share code, notes, and snippets.

@leonoel
Created April 16, 2022 19:10
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 leonoel/7e6cb47399f6fc7d387e393e2d7de74a to your computer and use it in GitHub Desktop.
Save leonoel/7e6cb47399f6fc7d387e393e2d7de74a to your computer and use it in GitHub Desktop.
cloroutine performance
(ns ^{:doc "
Performance measurements for various generator implementations, cloroutine v10 https://github.com/leonoel/cloroutine
Based on https://clojureverse.org/t/how-to-transform-nested-map-into-flat-sequence-of-path-value-pairs/8801/22
"} cloroutine-perf
(:require [cloroutine.core :refer [cr]]))
(def ^:dynamic *tail*)
(defn gen-seq-dv [gen]
(lazy-seq (binding [*tail* (gen-seq-dv gen)] (gen))))
(defn yield-seq-dv [x]
(cons x *tail*))
(defn no-op [])
(defmacro generator-seq-dv [& body]
`(gen-seq-dv (cr {yield-seq-dv no-op} ~@body nil)))
(let [tl (ThreadLocal.)]
(defn gen-seq-tl [gen]
(lazy-seq
(let [prev (.get tl)]
(.set tl (gen-seq-tl gen))
(try (gen) (finally (.set tl prev))))))
(defn yield-seq-tl [x]
(cons x (.get tl))))
(defmacro generator-seq-tl [& body]
`(gen-seq-tl (cr {yield-seq-tl no-op} ~@body nil)))
(defn gen-reduce [ctor]
(reify
clojure.lang.IReduceInit
(reduce [_ f i]
(let [gen (ctor)]
(loop [r i]
(if (reduced? r)
@r (let [x (gen)]
(case x
::done r
(recur (f r x))))))))
java.lang.Iterable
(iterator [_]
(let [gen (ctor)
cur (clojure.lang.Box. (gen))]
(reify java.util.Iterator
(next [_]
(let [x (.-val cur)]
(set! (.-val cur) (gen)) x))
(hasNext [_] (not= ::done (.-val cur))))))))
(def yield-reduce identity)
(defmacro generator-reduce [& body]
`(gen-reduce #(cr {yield-reduce no-op} ~@body ::done)))
(defn last-rf
([])
([r] r)
([_ x] x))
(comment
;; lazy-seq, cloroutine with dynamic var (tutorial implemention)
(time (dotimes [i 10] (last (take 1000000 (generator-seq-dv (loop [] (yield-seq-dv :a) (recur)))))))
"Elapsed time: 5420.276562 msecs"
;; lazy-seq, cloroutine with thread local
(time (dotimes [i 10] (last (take 1000000 (generator-seq-tl (loop [] (yield-seq-tl :a) (recur)))))))
"Elapsed time: 1573.082021 msecs"
;; lazy-seq, naive implementation
(time (dotimes [i 10] (last (take 1000000 ((fn repeat-l [x] (lazy-seq (cons x (repeat-l x)))) :a)))))
"Elapsed time: 1132.88954 msecs"
;; lazy-seq, core implementation
(time (dotimes [i 10] (last (take 1000000 (repeat :a)))))
"Elapsed time: 896.978254 msecs"
;; reducible, cloroutine
(time (dotimes [i 10] (transduce (take 1000000) last-rf (generator-reduce (loop [] (yield-reduce :a) (recur))))))
"Elapsed time: 357.013956 msecs"
;; reducible, core implementation
(time (dotimes [i 10] (transduce (take 1000000) last-rf (repeat :a))))
"Elapsed time: 166.334069 msecs"
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment