A Clojure library for profiling.
This library is available on Clojars; here is the Leiningen dependency for the most recently released version:
If you use CIDER in Emacs, check out
nrepl-profile, a project
that provides nREPL middleware that takes advantage of this
project. (The Emacs portions of the nrepl-profile are available in
MELPA as cider-profile.
The goal of this project is to work toward integration into CIDER, the Clojure IDE for Emacs. The stats collected are the as follows:
:nNumber of samples.:sumAggregate time spent in fn.:q1First quartile i.e. twenty-fifth percentile.:medMedian i.e. fiftieth percentile.:q3Third quartile i.e. seventy-fifth percentile.:sdStandard deviation i.e. the square root of the sum of squares of differences from the mean.:madMean average deviation, I don't feel like looking up the definition just now.
Full API documentation is available.
After writing profile, I was puttering around CrossClj, I came
across Stuart Sierra's circa 2009 core.contrib.profile library. He
made some different decisions than I did in his implementation,
notably:
-
Sierra's library is written to reduce to a nop unless an earmuffed var evaluates to true. This library always incurs profiling overhead for any profiled var.
-
Sierra's library does not keep sample data but instead reduces the incoming sample data with each traced invocation. This library does, so that it can compute mean average deviation on an optionally rolling sample of the most recent invocations for a given var.
-
Sierra's library allows arbitrary bodies of code to be profiled. This library only profiles functions bound to vars.
These differences are due in large part because thunknyc/profile is
intended to be used interactively in an IDE. Also, its API is modelled
on clojure.org/tools.trace, which focuses on tracing (and
un-tracing) vars.
People have mentioned Criterium. Criterium looks great! Definitely use it if it works for you. That said, it doesn't work well for non-idempotent, non-referentially transparent profiling. I wrote this library primarily to assist in understanding the performance characteristics of code that is highly dependent on interactions outside the JVM, for example due to HTTP requests, database queries, sending pub-sub messages, things like those.
(require '[profile.core :refer :all])
(defn my-add [a b] (+ a b))
(defn my-mult [a b] (* a b))
(profile-vars my-add my-mult)
(profile {}
(my-add (my-mult (rand-int 100000) (rand-int 1000000))
(my-mult (rand-int 100000) (rand-int 1000000))))profile prints output to *err* using pprint/print-table; it
looks like this:
| :name | :n | :sum | :q1 | :med | :q3 | :sd | :mad |
|----------------+----+------+-----+------+-----+-----+------|
| #'user/my-add | 1 | 2µs | 2µs | 2µs | 2µs | 0µs | 0µs |
| #'user/my-mult | 2 | 11µs | 3µs | 8µs | 3µs | 3µs | 5µs |
| :stat | :value |
|----------+--------|
| :agg-sum | 13µs |
Copyright © 2014 Edwin Watkeys
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.