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
(let [nanosecs# nthreads 1}} & body]
(if-not ~num-threads `(let [nlaps# ~nlaps
(time-ns (dotimes [_# ~num-laps] ~form)) nlaps-warmup# ~nlaps-warmup
(let [laps-per-thread# (int (/ ~num-laps ~num-threads))] nthreads# ~nthreads]
(time-ns (try (dotimes [_# nlaps-warmup#] ~@body)
(->> (fn [] (future (dotimes [_# laps-per-thread#] ~form))) (let [nanosecs#
(repeatedly ~num-threads) (if (= nthreads# 1)
doall (time-ns (dotimes [_# nlaps#] ~@body))
(map deref) (let [nlaps-per-thread# (int (/ nlaps# nthreads#))]
dorun))))] (time-ns
(if ~as-ns? nanosecs# (Math/round (/ nanosecs# 1000000.0)))) (->> (fn [] (future (dotimes [_# nlaps-per-thread#] ~@body)))
(catch Exception e# (str "DNF: " (.getMessage e#))))) (repeatedly nthreads#)
(doall)
(defn version-compare "Comparator for version strings like x.y.z, etc." (map deref)
[x y] (let [vals (fn [s] (vec (map #(Integer/parseInt %) (str/split s #"\."))))] (dorun)))))]
(compare (vals x) (vals y)))) (if ~as-ns? nanosecs# (Math/round (/ nanosecs# 1000000.0))))
(catch Exception e# (format "DNF: %s" (.getMessage e#))))))
(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 @dv
(let [dv (delay (apply f args))] (locking cache ; For thread racing
(swap! cache assoc args dv) (if-let [dv (@cache args)] ; Retry after lock acquisition!
@dv)))) @dv
(let [dv (delay (apply f args))]
(swap! cache assoc args dv)
@dv))))))
(comment (memoized nil +) (comment (memoized nil +)
(memoized nil + 5 12)) (memoized nil + 5 12))