Liking cljdoc? Tell your friends :D

taoensso.tufte

A simple, fast, monitoring profiler for Clojure/Script.

Usage: wrap+name interesting body exprs with the p macro. Then activate profiling of these wrapped exprs using the profiled or profile macros:

(profiled {} (p :my-fn (my-fn))) ; Returns [<body-result> <?pstats>] (profile {} (p :my-fn (my-fn))) ; Returns <body-result>, dispatches ; ?pstats to any registered handlers.

Extensive facilities are provided for compile-time elision and runtime filtering.

See the relevant docstrings for more info: p, profiled, profile, add-handler! ; Core API

(p [opts & body] [id & body]) ; e.g. (p ::my-pid (do-work)) (profiled [opts & body]) ; e.g. (profiled {:level 2} (my-fn)) (profile [opts & body]) ; e.g. (profiled {:level 2} (my-fn))

(add-handler! [handler-id ns-pattern handler-fn])

How/where to use this library: Tufte profiling is highly optimized: even without elision, you can usually leave profiling enabled in production (e.g. for sampled profiling, or to detect unusual performance behaviour). Tufte's stats maps are well suited to programmatic monitoring.

A simple, fast, monitoring profiler for Clojure/Script.

Usage: wrap+name interesting body exprs with the `p` macro. Then activate
profiling of these wrapped exprs using the `profiled` or `profile` macros:

  (profiled {} (p :my-fn (my-fn))) ; Returns [<body-result> <?pstats>]
  (profile  {} (p :my-fn (my-fn))) ; Returns  <body-result>, dispatches
                                   ; ?pstats to any registered handlers.

Extensive facilities are provided for compile-time elision and runtime
filtering.

See the relevant docstrings for more info:
  `p`, `profiled`, `profile`, `add-handler!` ; Core API

  (p        [opts & body] [id & body]) ; e.g. `(p ::my-pid (do-work))`
  (profiled [opts & body])             ; e.g. `(profiled {:level 2} (my-fn))`
  (profile  [opts & body])             ; e.g. `(profiled {:level 2} (my-fn))`

  (add-handler! [handler-id ns-pattern handler-fn])

How/where to use this library:
  Tufte profiling is highly optimized: even without elision, you can usually
  leave profiling enabled in production (e.g. for sampled profiling, or to
  detect unusual performance behaviour). Tufte's stats maps are well suited
  to programmatic monitoring.
raw docstring

*min-level*clj/s

e/o #{0 1 2 3 4 5 6}

e/o #{0 1 2 3 4 5 6}
raw docstring

*ns-filter*clj/s

(fn [?ns] -> truthy).

(fn [?ns] -> truthy).
raw docstring

-compile-ns-filterclj/s


-elide?clj

(-elide? level-form ns-str-form)

Returns true iff level or ns are compile-time filtered.

Returns true iff level or ns are compile-time filtered.
raw docstring

accumulate-statsclj/s

(accumulate-stats stats-accumulator [result ?pstats])

Experimental, subject to change!

Experimental, subject to change!
raw docstring

add-basic-println-handler!clj/s

(add-basic-println-handler! {:keys [ns-pattern format-columns]
                             :or {ns-pattern "*"
                                  format-columns stats/all-format-columns}})

Adds a simple handler that logs profile stats output with println.

Adds a simple handler that logs `profile` stats output with `println`.
raw docstring

add-handler!clj/s

(add-handler! handler-id handler-fn)
(add-handler! handler-id ns-pattern handler-fn)

Use this to register interest in stats output produced by profile calls. Each registered handler-fn will be called as:

(handler-fn {:ns-str _ :level _ :?id _ :?data _ :pstats _ :pstats-str_ _})

Map args: :ns-str - Namespace string where profile call took place :level - Level e/o #{0 1 2 3 4 5}, given in (profile {:level _} ...) :?id - Optional id, given in (profile {:id _} ...) :?data - Optional arb data, given in (profile {:data _} ...) :pstats - As in (second (profiled ...)). Derefable, mergeable. :pstats-str_ - `(delay (format-pstats pstats))

Error handling (NB): Handler errors will be silently swallowed. Please try/catch and appropriately deal with (e.g. log) possible errors within handler-fn.

Async/blocking: handler-fn should ideally be non-blocking, or reasonably cheap. Handler dispatch occurs through a 1-thread 1k-buffer dropping queue.

Ns filtering: Provide an optional ns-pattern arg to only call handler for matching namespaces. See compile-ns-filter docstring for details on ns-pattern.

Handler ideas: Save to a db, log, put! to an appropriate core.async channel, filter, aggregate, use for a realtime analytics dashboard, examine for outliers or unexpected output, ...

Use this to register interest in stats output produced by `profile` calls.
Each registered `handler-fn` will be called as:

  (handler-fn {:ns-str _ :level _ :?id _ :?data _ :pstats _ :pstats-str_ _})

Map args:
  :ns-str      - Namespace string where `profile` call took place
  :level       - Level e/o #{0 1 2 3 4 5}, given in `(profile {:level _} ...)`
  :?id         - Optional id,              given in `(profile {:id    _} ...)`
  :?data       - Optional arb data,        given in `(profile {:data  _} ...)`
  :pstats      - As in `(second (profiled ...))`. Derefable, mergeable.
  :pstats-str_ - `(delay (format-pstats pstats))

Error handling (NB):
  Handler errors will be silently swallowed. Please `try`/`catch` and
  appropriately deal with (e.g. log) possible errors *within* `handler-fn`.

Async/blocking:
  `handler-fn` should ideally be non-blocking, or reasonably cheap. Handler
   dispatch occurs through a 1-thread 1k-buffer dropping queue.

Ns filtering:
  Provide an optional `ns-pattern` arg to only call handler for matching
  namespaces. See `compile-ns-filter` docstring for details on `ns-pattern`.

Handler ideas:
  Save to a db, log, `put!` to an appropriate `core.async` channel, filter,
  aggregate, use for a realtime analytics dashboard, examine for outliers
  or unexpected output, ...
raw docstring

capture-time!clj/s

(capture-time! id nano-secs-elapsed)
(capture-time! pdata id nano-secs-elapsed)

Note: this is a low-level primitive for advanced users! Can be useful when tracking time across arbitrary thread boundaries or for async jobs / callbacks / etc.

See new-pdata for more info on low-level primitives.

Note: this is a low-level primitive for advanced users!
Can be useful when tracking time across arbitrary thread boundaries or for
async jobs / callbacks / etc.

See `new-pdata` for more info on low-level primitives.
raw docstring

chanceclj/s

(chance p)

Returns true with 0<p<1 probability.

Returns true with 0<`p`<1 probability.
raw docstring

compile-ns-filterclj/s

(compile-ns-filter ns-pattern)

Returns (fn [?ns]) -> truthy. Some example patterns: "foo.bar", "foo.bar.", #{"foo" "bar"}, {:whitelist ["foo.bar."] :blacklist ["baz.*"]}

Returns (fn [?ns]) -> truthy. Some example patterns:
"foo.bar", "foo.bar.*", #{"foo" "bar"},
{:whitelist ["foo.bar.*"] :blacklist ["baz.*"]}
raw docstring

defnpclj/s≠macro

clj
(defnp name doc-string? attr-map? [params*] prepost-map? body)
(defnp name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?)
cljs
(defnp & sigs)

Like defn but wraps fn bodies with p macro.

Like `defn` but wraps fn bodies with `p` macro.
raw docstring

defnp-clj/s≠macro

clj
(defnp- name doc-string? attr-map? [params*] prepost-map? body)
(defnp- name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?)
cljs
(defnp- & sigs)

Like defn- but wraps fn bodies with p macro.

Like `defn-` but wraps fn bodies with `p` macro.
raw docstring

fnpclj/s≠macro

clj
(fnp name? ([params*] prepost-map? body) +)
(fnp name? [params*] prepost-map? body)
cljs
(fnp & sigs)

Like fn but wraps fn bodies with p macro.

Like `fn` but wraps fn bodies with `p` macro.
raw docstring

format-pstatsclj/s

(format-pstats ps & [{:keys [columns] :or {columns stats/all-format-columns}}])

Formats given pstats to a string table. Accounted < Clock => Some work was done that wasn't tracked by any p forms. Accounted > Clock => Nested p forms, and/or parallel threads.

Formats given pstats to a string table.
Accounted < Clock => Some work was done that wasn't tracked by any p forms.
Accounted > Clock => Nested p forms, and/or parallel threads.
raw docstring

handlers_clj/s

{<handler-id> <handler-fn>}

{<handler-id> <handler-fn>}
raw docstring

HandlerValcljs


may-profile?clj/s

(may-profile? level)
(may-profile? level ns)

Returns true iff level and ns are runtime unfiltered.

Returns true iff level and ns are runtime unfiltered.
raw docstring

merge-pstatsclj/s

(merge-pstats)
(merge-pstats ps0)
(merge-pstats ps0 ps1)

Lossless unless data to merge are very large.

Lossless unless data to merge are very large.
raw docstring

new-pdataclj/s

(new-pdata)
(new-pdata {:keys [dynamic? nmax] :or {dynamic? true nmax default-nmax}})

Note: this is a low-level primitive for advanced users! Returns a new pdata object for use with with-profiling and/or capture-time!. Deref to get pstats:

(let [pd (new-pdata) t0 (System/nanoTime)] (with-profiling pd {} (p :foo (Thread/sleep 100)) (capture-time! pd :bar (- t0 (System/nanoTime)))) @pd)

Dynamic (thread-safe) by default. WARNING: don't change this default unless you're very sure the resulting pdata object will not be concurrently modified across threads. Concurrent modification will lead to bad data and/or exceptions!

Note: this is a low-level primitive for advanced users!
Returns a new pdata object for use with `with-profiling` and/or `capture-time!`.
Deref to get pstats:

  (let [pd (new-pdata)
        t0 (System/nanoTime)]
    (with-profiling pd {}
      (p :foo (Thread/sleep 100))
      (capture-time! pd :bar (- t0 (System/nanoTime))))
    @pd)

Dynamic (thread-safe) by default.
*WARNING*: don't change this default unless you're very sure the resulting
pdata object will not be concurrently modified across threads. Concurrent
modification will lead to bad data and/or exceptions!
raw docstring

pclj/smacro

(p id & body)
(p opts & body)

Profiling spy. Always executes body, and always returns <body-result>.

When [ns level] unelided and profiling is active, records execution time of body.

Compile-time opts: :id - Id for this body in stats output (e.g. ::my-fn-call) :level - e/o #{0 1 2 3 4 5} ; Default is 5

Profiling spy. Always executes body, and always returns <body-result>.

When [ns level] unelided and profiling is active, records execution
time of body.

Compile-time opts:
 :id    - Id for this body in stats output (e.g. `::my-fn-call`)
 :level - e/o #{0 1 2 3 4 5} ; Default is `5`
raw docstring

profileclj/smacro

(profile opts & body)

Always executes body, and always returns <body-result>.

When [ns level] unelided and [ns level when] unfiltered, executes body with profiling active and dispatches stats to any registered handlers (see add-handler!).

Handy if you'd like to consume/aggregate stats output later/elsewhere. Otherwise see profiled.

Compile-time opts: :level - e/o #{0 1 2 3 4 5} ; Default is 5 :dynamic? - Use multi-threaded profiling? ; Default is false :nmax - ~Max captures per id before compaction ; Default is 8e5 :when - Optional arbitrary conditional form (e.g. boolean expr) :id - Optional stats id provided to handlers (e.g. ::my-stats-1) :data - Optional arbitrary data provided to handlers

Note on laziness: Please note that lazy seqs and other forms of laziness (e.g. delays) will only contribute to profiling results if/when evaluation actually occurs. This is intentional and a useful property. Compare:

(profiled {} (delay (Thread/sleep 2000))) ; Doesn't count sleep (profiled {} @(delay (Thread/sleep 2000))) ; Does count sleep

Always executes body, and always returns <body-result>.

When [ns level] unelided and [ns level `when`] unfiltered, executes body
with profiling active and dispatches stats to any registered handlers
(see `add-handler!`).

Handy if you'd like to consume/aggregate stats output later/elsewhere.
Otherwise see `profiled`.

Compile-time opts:
  :level    - e/o #{0 1 2 3 4 5} ; Default is `5`
  :dynamic? - Use multi-threaded profiling? ; Default is `false`
  :nmax     - ~Max captures per id before compaction ; Default is 8e5
  :when     - Optional arbitrary conditional form (e.g. boolean expr)
  :id       - Optional stats id provided to handlers (e.g. `::my-stats-1`)
  :data     - Optional arbitrary data provided to handlers

Note on laziness:
  Please note that lazy seqs and other forms of laziness (e.g. delays)
  will only contribute to profiling results if/when evaluation actually
  occurs. This is intentional and a useful property. Compare:

  (profiled {}  (delay (Thread/sleep 2000))) ; Doesn't count sleep
  (profiled {} @(delay (Thread/sleep 2000))) ; Does count sleep
raw docstring

profiledclj/smacro

(profiled opts & body)

Always executes body, and always returns [<body-result> <?pstats>].

When [ns level] unelided and [ns level when] unfiltered, executes body with profiling active.

Handy if you'd like to consume stats output directly. Otherwise see profile.

pstats objects are derefable and mergeable:

  • @pstats -> {:stats {:n _ :min _ ...} :clock {:t0 _ :t1 _ :total _}}
  • @(merge-pstats ps1 ps2) -> {:stats {:n _ :min _ ...} :clock {:t0 _ :t1 _ :total _}}

Full set of :stats keys: :n :min :max :mean :mad :sum :p50 :p90 :p95 :p99

Compile-time opts: :level - e/o #{0 1 2 3 4 5} ; Default is 5 :dynamic? - Use multi-threaded profiling? ; Default is false :nmax - ~Max captures per id before compaction ; Default is 8e5 :when - Optional arbitrary conditional form (e.g. boolean expr)

Note on laziness: Please note that lazy seqs and other forms of laziness (e.g. delays) will only contribute to profiling results if/when evaluation actually occurs. This is intentional and a useful property. Compare:

(profiled {} (delay (Thread/sleep 2000))) ; Doesn't count sleep (profiled {} @(delay (Thread/sleep 2000))) ; Does counts sleep

Always executes body, and always returns [<body-result> <?pstats>].

When [ns level] unelided and [ns level `when`] unfiltered, executes body
with profiling active.

Handy if you'd like to consume stats output directly.
Otherwise see `profile`.

`pstats` objects are derefable and mergeable:
  - @pstats                 -> {:stats {:n _ :min _ ...} :clock {:t0 _ :t1 _ :total _}}
  - @(merge-pstats ps1 ps2) -> {:stats {:n _ :min _ ...} :clock {:t0 _ :t1 _ :total _}}

Full set of `:stats` keys:
  :n :min :max :mean :mad :sum :p50 :p90 :p95 :p99

Compile-time opts:
  :level    - e/o #{0 1 2 3 4 5} ; Default is `5`
  :dynamic? - Use multi-threaded profiling? ; Default is `false`
  :nmax     - ~Max captures per id before compaction ; Default is 8e5
  :when     - Optional arbitrary conditional form (e.g. boolean expr)

Note on laziness:
  Please note that lazy seqs and other forms of laziness (e.g. delays)
  will only contribute to profiling results if/when evaluation actually
  occurs. This is intentional and a useful property. Compare:

  (profiled {}  (delay (Thread/sleep 2000))) ; Doesn't count sleep
  (profiled {} @(delay (Thread/sleep 2000))) ; Does counts sleep
raw docstring

profiling?clj/s

(profiling?)

Returns e/o #{nil :thread :dynamic}.

Returns e/o #{nil :thread :dynamic}.
raw docstring

pspyclj/smacro

(pspy & args)

p alias

`p` alias
raw docstring

refer-tufteclj

(refer-tufte)

(require '[taoensso.tufte :as tufte :refer [defnp p profiled profile]])

(require '[taoensso.tufte :as tufte :refer [defnp p profiled profile]])
raw docstring

remove-handler!clj/s

(remove-handler! handler-id)

set-min-level!clj/s

(set-min-level! level)

Sets root binding of minimum profiling level, e/o #{0 1 2 3 4 5 6}. 0 => Enable all profiling. 6 => Disable all profiling.

Sets root binding of minimum profiling level, e/o #{0 1 2 3 4 5 6}.
0 => Enable  all profiling.
6 => Disable all profiling.
raw docstring

set-ns-pattern!clj/s

(set-ns-pattern! ns-pattern)

Sets root binding of namespace filter. See compile-ns-filter docstring for details on ns-pattern arg.

Sets root binding of namespace filter.
See `compile-ns-filter` docstring for details on `ns-pattern` arg.
raw docstring

stats-accumulatorclj/s

(stats-accumulator)
(stats-accumulator init-pstats)

Experimental, subject to change! Small util to help collect (merge) pstats from multiple runs or threads.

Returns a stateful StatsAccumulator, acc:

  • @acc ; Returns current pstats
  • (acc <pstats>) ; Synchronously merges given pstats into accumulator

Note that you may want some kind of async/buffer/serialization mechanism in front of merge calls (e.g. an agent).

Experimental, subject to change!
Small util to help collect (merge) pstats from multiple runs or threads.

Returns a stateful StatsAccumulator, `acc`:
  - `@acc`           ; Returns current pstats
  - `(acc <pstats>)` ; Synchronously merges given pstats into accumulator

Note that you may want some kind of async/buffer/serialization mechanism in
front of merge calls (e.g. an agent).
raw docstring

StatsAccumulatorcljs


valid-min-levelclj/s

(valid-min-level x)

valid-min-level?clj/s

(valid-min-level? x)

valid-run-levelclj/s

(valid-run-level x)

valid-run-level?clj/s

(valid-run-level? x)

with-min-levelclj/smacro

(with-min-level level & body)

Executes body with dynamic minimum profiling level, e/o #{0 1 2 3 4 5 6}. 0 => Enable all profiling. 6 => Disable all profiling.

Executes body with dynamic minimum profiling level, e/o #{0 1 2 3 4 5 6}.
0 => Enable  all profiling.
6 => Disable all profiling.
raw docstring

with-ns-patternclj/smacro

(with-ns-pattern ns-pattern & body)

Executes body with dynamic namespace filter. See compile-ns-filter docstring for details on ns-pattern arg.

Executes body with dynamic namespace filter.
See `compile-ns-filter` docstring for details on `ns-pattern` arg.
raw docstring

with-profilingclj/smacro

(with-profiling pdata {:keys [dynamic? nmax] :or {nmax default-nmax}} & body)

Note: this is a low-level primitive for advanced users! Enables p forms in body and returns body's result.

See new-pdata for more info on low-level primitives.

Note: this is a low-level primitive for advanced users!
Enables `p` forms in body and returns body's result.

See `new-pdata` for more info on low-level primitives.
raw docstring

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close