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 scratch).
Would anyone else find these useful? Some snippets: user> (defn work [] (reduce + (doall (map identity (range 500000))))) #'user/work user> (work) 124999750000 ; A simple function that does some work user> (time (do (dotimes [_ 10] (work)) "done")) "Elapsed time: 6929.528 msecs" "done" ; The usual time macro user> (get-time (do (dotimes [_ 10] (work)) "done")) 6754.874 ; 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) :timeout ; 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 thread. ; 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) :memout user> (time-and-memory-limit (do (dotimes [_ 10] (timeout) (work)) "done") 5 100) :timeout ; 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. http://paste.lisp.org/display/76181 Comments and suggestions welcome. Cheers, Jason --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---