Utils: housekeeping, update bench, memoized

This commit is contained in:
Peter Taoussanis 2013-11-08 21:45:28 +07:00
parent 08e28748be
commit 730b8774c4
2 changed files with 29 additions and 29 deletions

View file

@ -8,7 +8,7 @@
;; Remove stuff from stress-data that breaks reader ;; Remove stuff from stress-data that breaks reader
(def data (dissoc nippy/stress-data :queue :queue-empty :bytes)) (def data (dissoc nippy/stress-data :queue :queue-empty :bytes))
(defmacro bench* [& body] `(utils/bench 10000 (do ~@body) :warmup-laps 20000)) (defmacro bench* [& body] `(utils/bench 10000 {:warmup-laps 20000} ~@body))
(defn bench1 [freezer thawer & [sizer]] (defn bench1 [freezer thawer & [sizer]]
(let [data-frozen (freezer data) (let [data-frozen (freezer data)
time-freeze (bench* (freezer data)) time-freeze (bench* (freezer data))

View file

@ -35,41 +35,41 @@
[& body] `(let [t0# (System/nanoTime)] ~@body (- (System/nanoTime) t0#))) [& body] `(let [t0# (System/nanoTime)] ~@body (- (System/nanoTime) t0#)))
(defmacro bench (defmacro bench
"Repeatedly executes form and returns time taken to complete execution." "Repeatedly executes body and returns time taken to complete execution."
[num-laps form & {:keys [warmup-laps num-threads as-ns?]}] [nlaps {:keys [nlaps-warmup nthreads as-ns?]
`(try (when ~warmup-laps (dotimes [_# ~warmup-laps] ~form)) :or {nlaps-warmup 0
nthreads 1}} & body]
`(let [nlaps# ~nlaps
nlaps-warmup# ~nlaps-warmup
nthreads# ~nthreads]
(try (dotimes [_# nlaps-warmup#] ~@body)
(let [nanosecs# (let [nanosecs#
(if-not ~num-threads (if (= nthreads# 1)
(time-ns (dotimes [_# ~num-laps] ~form)) (time-ns (dotimes [_# nlaps#] ~@body))
(let [laps-per-thread# (int (/ ~num-laps ~num-threads))] (let [nlaps-per-thread# (int (/ nlaps# nthreads#))]
(time-ns (time-ns
(->> (fn [] (future (dotimes [_# laps-per-thread#] ~form))) (->> (fn [] (future (dotimes [_# nlaps-per-thread#] ~@body)))
(repeatedly ~num-threads) (repeatedly nthreads#)
doall (doall)
(map deref) (map deref)
dorun))))] (dorun)))))]
(if ~as-ns? nanosecs# (Math/round (/ nanosecs# 1000000.0)))) (if ~as-ns? nanosecs# (Math/round (/ nanosecs# 1000000.0))))
(catch Exception e# (str "DNF: " (.getMessage e#))))) (catch Exception e# (format "DNF: %s" (.getMessage e#))))))
(defn version-compare "Comparator for version strings like x.y.z, etc."
[x y] (let [vals (fn [s] (vec (map #(Integer/parseInt %) (str/split s #"\."))))]
(compare (vals x) (vals y))))
(defn version-sufficient? [version-str min-version-str]
(try (>= (version-compare version-str min-version-str) 0)
(catch Exception _ false)))
(defn memoized (defn memoized
"Like `memoize` but takes an explicit cache atom (possibly nil) and "Like `(partial memoize* {})` but takes an explicit cache atom (possibly nil)
immediately applies memoized f to given arguments." and immediately applies memoized f to given arguments."
[cache f & args] [cache f & args]
(if-not cache (if-not cache
(apply f args) (apply f args)
(if-let [dv (@cache args)] (if-let [dv (@cache args)]
@dv
(locking cache ; For thread racing
(if-let [dv (@cache args)] ; Retry after lock acquisition!
@dv @dv
(let [dv (delay (apply f args))] (let [dv (delay (apply f args))]
(swap! cache assoc args dv) (swap! cache assoc args dv)
@dv)))) @dv))))))
(comment (memoized nil +) (comment (memoized nil +)
(memoized nil + 5 12)) (memoized nil + 5 12))