Timing utilities for clojure.contrib?

Skip to first unread message

Jason Wolfe

Feb 25, 2009, 9:28:51 PM2/25/09
to Clojure
I wrote a small set of functions for executing code while measuring
and/or limiting its time and/or memory consumption. I did this both
to run timing experiments, and to let me run things at the REPL
without risking an infinite loop (and having to restart Clojure from

Would anyone else find these useful?

Some snippets:

user> (defn work [] (reduce + (doall (map identity (range 500000)))))
user> (work)

; A simple function that does some work

user> (time (do (dotimes [_ 10] (work)) "done"))
"Elapsed time: 6929.528 msecs"

; The usual time macro

user> (get-time (do (dotimes [_ 10] (work)) "done"))

; get-time returns the amount of time taken (in ms), and throws away
the value returned

user> (get-time-pair (do (dotimes [_ 10] (work)) "done"))
["done" 6729.438]

; get-time-pair returns both the value and the time taken

user> (time-limit (do (dotimes [_ 10] (timeout) (work)) "done") 10)
["done" 6808.941]

user> (time-limit (do (dotimes [_ 10] (timeout) (work)) "done") 5)

; time-limit runs the first form for at most x seconds, returning the
result of get-time-pair
; if the run completed, and otherwise kills the execution of the form
and returns :timeout.
; This is implemented by running your form in a separate Future
; If your worker doesn't do any blocking IO, it should call "timeout"
periodically as you see here
; (which is fairly low-overhead). It seems impossible to get around
this limitation.

user> (time-and-memory-limit (do (dotimes [_ 10] (timeout) (work))
"done") 10 100)
["done" 6283.163]
user> (time-and-memory-limit (do (dotimes [_ 10] (timeout) (work))
"done") 10 5)
user> (time-and-memory-limit (do (dotimes [_ 10] (timeout) (work))
"done") 5 100)

; time-and-memory-limit is like time-limit, but also imposes a heap
growth limitation (in MB).
; Memory instrumenting is tricky; the method I use is not perfect, but
should give reasonable
; numbers as long as you're not getting close to the limit (in which
case forced GCs will slow
; things down).

user> (time-and-memory-instrument (do (dotimes [_ 10] (timeout)
(work)) "done") 10 100)
["done" 6379.433 8.624679565429688]

; time-and-memory-instrument is like time-and-memory-limit, but it
also returns the max
; heap size growth (in MB). This may affect timing in a somewhat
unpredictable fashion,
; and the numbers are somewhat questionable, but it at least gives you
an idea how much
; memory your code is using.

My current code is posted here, if you're interested how it works.


Comments and suggestions welcome.

Reply all
Reply to author
0 new messages