sfertman / tic-toc

Code profiler for clojure, in clojure

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

tic-toc

Clojure code profiler. Very basic for now but possibly offers a quick and dirty way for exploratory optimization of bottlenecks. Does not drill down into fns definitions; does a simple postwalk on the input forms* and dumps results in one big atom for analysis.

Clojars Project

Profiling

Just wrap whatever with profile macro

(require '[tic-toc.core :refer :all])

(profile
  (let [n 5000]
    (doseq [i (range n)]
      (println (str "Hello world! #" i))
      (println (str (- n (inc i)) " more to go" )))))

; =>
; Hello world! #0
; 4999 more to go
; Hello world! #1
; 4998 more to go
; Hello world! #2
; ...
; ...
; ...
; Hello world! #4998
; 1 more to go
; Hello world! #4999
; 0 more to go
; nil

Run time summary

Metrics are accumulated in an atom metrics. Collects run time in nanoseconds for each unique function call. To see a quick summary use:

(pprint (summary))

; =>
; {"clojure.core/range"
;  {:total-time 113784,
;   :args-time 0,
;   :fn-time 113784,
;   :calls 1,
;   :mean-total 113784.0,
;   :mean-args 0.0,
;   :mean-fn 113784.0},
;  "clojure.core/str"
;  {:total-time 73567489,
;   :args-time 27101634,
;   :fn-time 46465855,
;   :calls 10000,
;   :mean-total 7356.7489,
;   :mean-args 2710.1634,
;   :mean-fn 4646.5855},
; ...
; ...
; ...
;  "clojure.core/let"
;  {:total-time 1429307487,
;   :args-time 1429296603,
;   :fn-time 10884,
;   :calls 1,
;   :mean-total 1.429307487E9,
;   :mean-args 1.429296603E9,
;   :mean-fn 10884.0}}
; nil

However, for more complex expressions this may be too big to look at. top will give the top 10 time consumers in the profiling session based on :fn-time:

(pprint (top))

; =>
; (["clojure.core/println" 1328577766]
;  ["clojure.core/doseq" 50735764]
;  ["clojure.core/str" 46465855]
;  ["clojure.core/-" 13821717]
;  ["clojure.core/inc" 13279917]
;  ["clojure.core/range" 113784]
;  ["clojure.core/let" 10884])
; nil

Raw data

Alternatively, you can access the raw data and pipe it to your favourite data analytics tool

(pprint (take 5 @metrics))

; =>
; ({:fn-id :clojure.core/range__1763,
;   :time-ns 113784,
;   :arg-fns []}
;  {:fn-id :clojure.core/str__1764,
;   :time-ns 15726,
;   :arg-fns []}
;  {:fn-id :clojure.core/println__1765,
;   :time-ns 415226,
;   :arg-fns [:clojure.core/str__1764]}
;  {:fn-id :clojure.core/inc__1766,
;   :time-ns 19302,
;   :arg-fns []}
;  {:fn-id :clojure.core/-__1767,
;   :time-ns 37854,
;   :arg-fns [:clojure.core/inc__1766]})
; nil

* Note that profile supports multiple inputs. Will return the value of the last input form. Metrics will be collected in the same atom for all forms and all subsequent calls to profile.

(profile
  (+ 42 43 44 45 46)
  (- 46 45 44 43 42)
  (* 1 2 3 4 5 6 7)
  (/ 46 45 44 43 42))

To start a fresh profiling session simply reset the metrics atom using:

(clear-session!)

About

Code profiler for clojure, in clojure

License:MIT License


Languages

Language:Clojure 100.0%