Skip to content

Commit 09c036d

Browse files
[profile] Update to latest profiling middleware
1 parent ddfc99b commit 09c036d

File tree

5 files changed

+58
-140
lines changed

5 files changed

+58
-140
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
- [#3789](https://github.com/clojure-emacs/cider/issues/3796): Completion: disable client-side sorting (defer to backend-provided candidate order).
2727
- [#3797](https://github.com/clojure-emacs/cider/issues/3797): Completion: enable `cider-completion-style` by default (this enables richer completion suggestions where candidates don't have to strictly match the prefix).
2828
- [#3803](https://github.com/clojure-emacs/cider/pull/3803): Enable dynamic indentation for `clojure-ts-mode`.
29+
- [#3805](https://github.com/clojure-emacs/cider/pull/3805): Profiler: update to latest profiling middleware.
2930

3031
### Bugs fixed
3132

cider-mode.el

+5-5
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ The result depends on the buffer CIDER connection type."
673673
(defface cider-traced-face
674674
'((((type graphic)) :box (:color "cyan" :line-width -1))
675675
(t :underline t :background "#066"))
676-
"Face used to mark code being traced."
676+
"Face used to mark functions being traced or profiled."
677677
:group 'cider
678678
:package-version '(cider . "0.11.0"))
679679

@@ -805,11 +805,11 @@ with the given LIMIT."
805805
(push sym instrumented))
806806
(`"\"light-form\""
807807
(push sym enlightened)))
808-
;; The ::traced keywords can be inlined by MrAnderson, so
809-
;; we catch that case too.
810808
;; FIXME: This matches values too, not just keys.
811-
(when (seq-find (lambda (k) (and (stringp k)
812-
(string-match (rx "orchard.trace/traced" eos) k)))
809+
(when (seq-find (lambda (k)
810+
(and (stringp k)
811+
(or (string= "orchard.trace/traced" k)
812+
(string= "orchard.profile/profiled" k))))
813813
meta)
814814
(push sym traced))
815815
(when (and do-deprecated (nrepl-dict-get meta "deprecated"))

cider-profile.el

+17-98
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
(require 'cider-client)
2929
(require 'cider-popup)
3030
(require 'cider-eval)
31+
(require 'cider-inspector)
3132

3233
(defconst cider-profile-buffer "*cider-profile*")
3334

@@ -37,16 +38,10 @@
3738
(define-key map (kbd "C-t") #'cider-profile-toggle)
3839
(define-key map (kbd "c") #'cider-profile-clear)
3940
(define-key map (kbd "C-c") #'cider-profile-clear)
40-
(define-key map (kbd "S") #'cider-profile-summary)
41-
(define-key map (kbd "C-S") #'cider-profile-summary)
42-
(define-key map (kbd "s") #'cider-profile-var-summary)
43-
(define-key map (kbd "C-s") #'cider-profile-var-summary)
41+
(define-key map (kbd "s") #'cider-profile-summary)
42+
(define-key map (kbd "C-s") #'cider-profile-summary)
4443
(define-key map (kbd "n") #'cider-profile-ns-toggle)
4544
(define-key map (kbd "C-n") #'cider-profile-ns-toggle)
46-
(define-key map (kbd "v") #'cider-profile-var-profiled-p)
47-
(define-key map (kbd "C-v") #'cider-profile-var-profiled-p)
48-
(define-key map (kbd "+") #'cider-profile-samples)
49-
(define-key map (kbd "C-+") #'cider-profile-samples)
5045
map)
5146
"CIDER profiler keymap.")
5247

@@ -55,9 +50,6 @@
5550
["Toggle var profiling" cider-profile-toggle]
5651
["Toggle namespace profiling" cider-profile-ns-toggle]
5752
"--"
58-
["Display var profiling status" cider-profile-var-profiled-p]
59-
["Display max sample count" cider-profile-samples]
60-
["Display var summary" cider-profile-var-summary]
6153
["Display summary" cider-profile-summary]
6254
["Clear data" cider-profile-clear])
6355
"CIDER profiling submenu.")
@@ -69,66 +61,20 @@ Optional argument BUFFER defaults to current buffer."
6961
(nrepl-make-response-handler
7062
(or buffer (current-buffer)) handler nil nil nil))
7163

72-
;;;###autoload
73-
(defun cider-profile-samples (&optional query)
74-
"Displays current max-sample-count.
75-
If optional QUERY is specified, set max-sample-count and display new value."
76-
(interactive "P")
77-
(cider-ensure-op-supported "set-max-samples")
78-
(cider-ensure-op-supported "get-max-samples")
79-
(if (not (null query))
80-
(cider-nrepl-send-request
81-
(let ((max-samples (if (numberp query) query '())))
82-
(message "query: %s" max-samples)
83-
`("op" "set-max-samples" "max-samples" ,max-samples))
84-
(cider-profile--make-response-handler
85-
(lambda (_buffer value)
86-
(let ((value (if (zerop (length value)) "unlimited" value)))
87-
(message "max-sample-count is now %s" value)))))
88-
(cider-nrepl-send-request
89-
'("op" "get-max-samples")
90-
(cider-profile--make-response-handler
91-
(lambda (_buffer value)
92-
(let ((value (if (zerop (length value)) "unlimited" value)))
93-
(message "max-sample-count is now %s" value))))))
94-
query)
95-
96-
;;;###autoload
97-
(defun cider-profile-var-profiled-p (query)
98-
"Displays the profiling status of var under point.
99-
Prompts for var if none under point or QUERY is present."
100-
(interactive "P")
101-
(cider-ensure-op-supported "is-var-profiled")
102-
(cider-read-symbol-name
103-
"Report profiling status for var: "
104-
(lambda (sym)
105-
(let ((ns (cider-current-ns)))
106-
(cider-nrepl-send-request
107-
`("op" "is-var-profiled"
108-
"ns" ,ns
109-
"sym" ,sym)
110-
(cider-profile--make-response-handler
111-
(lambda (_buffer value)
112-
(pcase value
113-
("profiled" (message "Profiling is currently enabled for %s/%s" ns sym))
114-
("unprofiled" (message "Profiling is currently disabled for %s/%s" ns sym))
115-
("unbound" (message "%s/%s is unbound" ns sym)))))))))
116-
query)
117-
11864
;;;###autoload
11965
(defun cider-profile-ns-toggle (&optional query)
12066
"Toggle profiling for the ns associated with optional QUERY.
12167
12268
If optional argument QUERY is non-nil, prompt for ns. Otherwise use
12369
current ns."
12470
(interactive "P")
125-
(cider-ensure-op-supported "toggle-profile-ns")
71+
(cider-ensure-op-supported "cider/profile-toggle-ns")
12672
(let ((ns (if query
12773
(completing-read "Toggle profiling for ns: "
12874
(cider-sync-request:ns-list))
12975
(cider-current-ns))))
13076
(cider-nrepl-send-request
131-
`("op" "toggle-profile-ns"
77+
`("op" "cider/profile-toggle-ns"
13278
"ns" ,ns)
13379
(cider-profile--make-response-handler
13480
(lambda (_buffer value)
@@ -143,69 +89,42 @@ current ns."
14389
Defaults to the symbol at point.
14490
With prefix arg or no symbol at point, prompts for a var."
14591
(interactive "P")
146-
(cider-ensure-op-supported "toggle-profile")
92+
(cider-ensure-op-supported "cider/profile-toggle-var")
14793
(cider-read-symbol-name
14894
"Toggle profiling for var: "
14995
(lambda (sym)
15096
(let ((ns (cider-current-ns)))
15197
(cider-nrepl-send-request
152-
`("op" "toggle-profile"
98+
`("op" "cider/profile-toggle-var"
15399
"ns" ,ns
154100
"sym" ,sym)
155101
(cider-profile--make-response-handler
156102
(lambda (_buffer value)
157103
(pcase value
158104
("profiled" (message "Profiling enabled for %s/%s" ns sym))
159-
("unprofiled" (message "Profiling disabled for %s/%s" ns sym))
160-
("unbound" (message "%s/%s is unbound" ns sym)))))))))
105+
("unprofiled" (message "Profiling disabled for %s/%s" ns sym)))))))))
161106
query)
162107

163-
(defun cider-profile-display-stats (stats-response)
164-
"Displays the STATS-RESPONSE on `cider-profile-buffer`."
165-
(let ((table (nrepl-dict-get stats-response "err")))
166-
(if cider-profile-buffer
167-
(let ((buffer (cider-make-popup-buffer cider-profile-buffer)))
168-
(with-current-buffer buffer
169-
(let ((inhibit-read-only t)) (insert table)))
170-
(display-buffer buffer)
171-
(let ((window (get-buffer-window buffer)))
172-
(set-window-point window 0)
173-
(select-window window)
174-
(fit-window-to-buffer window)))
175-
(cider-emit-interactive-eval-err-output table))))
108+
(defun cider-profile--send-to-inspector (summary-response)
109+
"Displays SUMMARY-RESPONSE using the inspector."
110+
(let ((value (nrepl-dict-get summary-response "value")))
111+
(cider-inspector--render-value value)))
176112

177113
;;;###autoload
178114
(defun cider-profile-summary ()
179115
"Display a summary of currently collected profile data."
180116
(interactive)
181-
(cider-ensure-op-supported "profile-summary")
182-
(cider-profile-display-stats
183-
(cider-nrepl-send-sync-request '("op" "profile-summary"))))
184-
185-
;;;###autoload
186-
(defun cider-profile-var-summary (query)
187-
"Display profile data for var under point QUERY.
188-
Defaults to the symbol at point. With prefix arg or no symbol at point,
189-
prompts for a var."
190-
(interactive "P")
191-
(cider-ensure-op-supported "profile-var-summary")
192-
(cider-read-symbol-name
193-
"Profile-summary for var: "
194-
(lambda (sym)
195-
(cider-profile-display-stats
196-
(cider-nrepl-send-sync-request
197-
`("op" "profile-var-summary"
198-
"ns" ,(cider-current-ns)
199-
"sym" ,sym)))))
200-
query)
117+
(cider-ensure-op-supported "cider/profile-summary")
118+
(cider-inspector--render-value
119+
(cider-nrepl-send-sync-request '("op" "cider/profile-summary"))))
201120

202121
;;;###autoload
203122
(defun cider-profile-clear ()
204123
"Clear any collected profile data."
205124
(interactive)
206-
(cider-ensure-op-supported "clear-profile")
125+
(cider-ensure-op-supported "cider/profile-clear")
207126
(cider-nrepl-send-request
208-
'("op" "clear-profile")
127+
'("op" "cider/profile-clear")
209128
(cider-profile--make-response-handler
210129
(lambda (_buffer value)
211130
(when (equal value "cleared")

doc/modules/ROOT/pages/config/syntax_highlighting.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,5 @@ should take care of them):
5656

5757
* `cider-deprecated-face` - used for syntax highlighting deprecated vars
5858
* `cider-instrumented-face` - used for syntax highlighting instrumented for debugging vars
59-
* `cider-traced-face` - used for syntax highlighting traced vars
59+
* `cider-traced-face` - used for syntax highlighting traced and profiled vars
6060
* `cider-reader-conditional-face` - used for syntax highlighting inactive reader conditional branches

doc/modules/ROOT/pages/debugging/profiling.adoc

+34-36
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,57 @@
11
= Profiling
22

3-
CIDER has a built-in profiler that can help you identify hot-spots in your
4-
application code. It's built on top of the https://github.com/thunknyc/profile[thunknyc/profile] library.
3+
CIDER has a simple built-in profiler that can you to quickly measure the running
4+
time of individual functions. It is similar to wrapping your functions with
5+
`time` macro, except it records every timing and displays a the summarized
6+
result.
7+
8+
NOTE: Profiling is different from benchmarking. Benchmarking more accurately
9+
tells you how long the code executes. If you need accurate timing results, use a
10+
serious benchmarking library like
11+
https://github.com/hugoduncan/criterium[Criterium]. If you need to understand
12+
where most of the time is spent, use a serious profiler like
13+
https://github.com/clojure-goes-fast/clj-async-profiler[clj-async-profiler].
514

615
NOTE: The profiler doesn't support ClojureScript.
716

817
== Usage
918

10-
Using CIDER's profiler is super easy. You'd just identify
11-
the vars you'd want to profile and invoke
12-
`M-x cider-profile-toggle` (kbd:[C-c C-= t]). By defaults it operates on the symbol
13-
at point, but will prompt for a var if there's nothing under the point.
19+
To start using CIDER profiler, choose the vars you want to profile and invoke
20+
`M-x cider-profile-toggle` (kbd:[C-c C-= t]). By defaults it operates on the
21+
symbol at point, but will prompt for a var if there's nothing under the point.
22+
You can also mark all functions in the namespace for profiling via
23+
`cider-profile-ns-toggle` (kbd:[C-c C-= n]).
1424

15-
TIP: There's also `cider-profile-ns-toggle` (kbd:[C-c C-= n]) that will profiles all vars in a
16-
namespace.
25+
Then, evaluate some code making use of those vars and their invocations will be
26+
automatically profiled.
1727

18-
Afterwards you can evaluate some code making use of those vars and their
19-
invocations will be automatically profiled.
20-
21-
You can display a report of the collected profiling data with `M-x cider-profile-summary` (kbd:[C-c C-= S]). If you'd like to limit the displayed data to a particular var you should try
22-
`M-x cider-profile-var-summary` (kbd:[C-c C-= s]).
28+
You can display a report of the collected profiling data with `M-x
29+
cider-profile-summary` (kbd:[C-c C-= s]).
2330

2431
== Understanding the Report Format
2532

26-
A typical profiling report looks something like this:
33+
Profiling reports are rendered by xref:debugging/inspector.adoc[CIDER
34+
inspector]. A typical profiling report looks like this:
2735

2836
....
29-
| :name | :n | :sum | :q1 | :med | :q3 | :sd | :mad |
30-
|----------------+----+------+-----+------+-----+-----+------|
31-
| #'user/my-add | 1 | 2µs | 2µs | 2µs | 2µs | 0µs | 0µs |
32-
| #'user/my-mult | 2 | 11µs | 3µs | 8µs | 3µs | 3µs | 5µs |
37+
| # | :name | :n | :mean | :std | :sum | :min | :max | :med | :samples |
38+
|---+-----------------+------+--------+---------+--------+--------+--------+--------+------------|
39+
| 0 | #'sample-ns/bar | 1000 | 3 us | ±14 us | 3 ms | 791 ns | 384 us | 2 us | [791 ...] |
40+
| 1 | #'sample-ns/baz | 1000 | 307 ns | ±710 ns | 307 us | 84 ns | 22 us | 250 ns | [84 ...] |
41+
| 2 | #'sample-ns/foo | 1000 | 7 us | ±18 us | 7 ms | 3 us | 495 us | 5 us | [2584 ...] |
42+
| 3 | #'sample-ns/qux | 1000 | 8 us | ±20 us | 8 ms | 3 us | 543 us | 5 us | [3125 ...] |
3343
....
3444

3545
Let's demystify all the column names:
3646

3747
* `:n`: Number of samples.
48+
* `:mean`: Average time spent in fn.
49+
* `:std`: Standard deviation.
3850
* `:sum`: Aggregate time spent in fn.
39-
* `:q1`: First quartile i.e. twenty-fifth percentile.
51+
* `:min`: Minimal recorded time for fn.
52+
* `:min`: Maximal recorded time for fn.
4053
* `:med`: Median i.e. fiftieth percentile.
41-
* `:q3`: Third quartile i.e. seventy-fifth percentile.
42-
* `:sd`: Standard deviation i.e. the square root of the sum of squares
43-
of differences from the mean.
44-
* `:mad`: Mean absolute deviation. See https://en.wikipedia.org/wiki/Average_absolute_deviation[this article] for more details.
54+
* `:samples`: A list of all timing samples. You can click it to see the full list in the inspector.
4555

4656
== Keybindings
4757

@@ -56,22 +66,10 @@ Let's demystify all the column names:
5666
| kbd:[C-c C-= n]
5767
| Toggle profiling for the current ns.
5868

59-
| `cider-profile-var-profiled-p`
60-
| kbd:[C-c C-= v]
61-
| Show whether some var has profiling enabled or not.
62-
63-
| `cider-profile-var-summary`
64-
| kbd:[C-c C-= s]
65-
| Display the profiling summary for some var.
66-
6769
| `cider-profile-summary`
68-
| kbd:[C-c C-= S]
70+
| kbd:[C-c C-= s]
6971
| Display the profiling summary for all vars.
7072

71-
| `cider-profile-samples`
72-
| kbd:[C-c C-= +]
73-
| Display or update `max-sample-count`.
74-
7573
| `cider-profile-clear`
7674
| kbd:[C-c C-= c]
7775
| Clear profiling data.

0 commit comments

Comments
 (0)