Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
marvel
GitHub Repository: marvel/qnf
Path: blob/master/elisp/slime/contrib/slime-sprof.el
990 views
1
2
(define-slime-contrib slime-sprof
3
"Integration with SBCL's sb-sprof."
4
(:authors "Juho Snellman"
5
"Stas Boukarev")
6
(:license "MIT")
7
(:swank-dependencies swank-sprof)
8
(:on-load
9
(let ((C '(and (slime-connected-p)
10
(equal (slime-lisp-implementation-type) "SBCL"))))
11
(setf (cdr (last (assoc "Profiling" slime-easy-menu)))
12
`("--"
13
[ "Start sb-sprof" slime-sprof-start ,C ]
14
[ "Stop sb-sprof" slime-sprof-stop ,C ]
15
[ "Report sb-sprof" slime-sprof-browser ,C ])))))
16
17
(defvar slime-sprof-exclude-swank nil
18
"*Display swank functions in the report.")
19
20
(define-derived-mode slime-sprof-browser-mode fundamental-mode
21
"slprof"
22
"Mode for browsing profiler data\
23
\\<slime-sprof-browser-mode-map>\
24
\\{slime-sprof-browser-mode-map}"
25
:syntax-table lisp-mode-syntax-table
26
(setq buffer-read-only t))
27
28
(set-keymap-parent slime-sprof-browser-mode-map slime-parent-map)
29
30
(slime-define-keys slime-sprof-browser-mode-map
31
("h" 'describe-mode)
32
("d" 'slime-sprof-browser-disassemble-function)
33
("g" 'slime-sprof-browser-go-to)
34
("v" 'slime-sprof-browser-view-source)
35
("s" 'slime-sprof-toggle-swank-exclusion)
36
((kbd "RET") 'slime-sprof-browser-toggle))
37
38
;; Start / stop profiling
39
40
(defun slime-sprof-start ()
41
(interactive)
42
(slime-eval `(swank:swank-sprof-start)))
43
44
(defun slime-sprof-stop ()
45
(interactive)
46
(slime-eval `(swank:swank-sprof-stop)))
47
48
;; Reporting
49
50
(defun slime-sprof-format (graph)
51
(with-current-buffer (slime-buffer-name :sprof)
52
(let ((inhibit-read-only t))
53
(erase-buffer)
54
(insert (format "%4s %-54s %6s %6s %6s\n"
55
"Rank"
56
"Name"
57
"Self%"
58
"Cumul%"
59
"Total%"))
60
(dolist (data graph)
61
(slime-sprof-browser-insert-line data 54))))
62
(goto-line 2))
63
64
(defun* slime-sprof-update (&optional (exclude-swank slime-sprof-exclude-swank))
65
(slime-eval-async `(swank:swank-sprof-get-call-graph
66
:exclude-swank ,exclude-swank)
67
'slime-sprof-format))
68
69
(defun slime-sprof-browser ()
70
(interactive)
71
(slime-with-popup-buffer ((slime-buffer-name :sprof)
72
:connection t
73
:select t
74
:mode 'slime-sprof-browser-mode)
75
(slime-sprof-update)))
76
77
(defun slime-sprof-toggle-swank-exclusion ()
78
(interactive)
79
(setq slime-sprof-exclude-swank
80
(not slime-sprof-exclude-swank))
81
(slime-sprof-update))
82
83
(defun slime-sprof-browser-insert-line (data name-length)
84
(destructuring-bind (index name self cumul total)
85
data
86
(if index
87
(insert (format "%-4d " index))
88
(insert " "))
89
(slime-insert-propertized
90
(slime-sprof-browser-name-properties)
91
(format (format "%%-%ds " name-length)
92
(abbreviate-name name name-length)))
93
(insert (format "%6.2f " self))
94
(when cumul
95
(insert (format "%6.2f " cumul))
96
(when total
97
(insert (format "%6.2f" total))))
98
(when index
99
(slime-sprof-browser-add-line-text-properties
100
`(profile-index ,index expanded nil)))
101
(insert "\n")))
102
103
(defun abbreviate-name (name max-length)
104
(lexical-let ((length (min (length name) max-length)))
105
(subseq name 0 length)))
106
107
;; Expanding / collapsing
108
109
(defun slime-sprof-browser-toggle ()
110
(interactive)
111
(let ((index (get-text-property (point) 'profile-index)))
112
(when index
113
(save-excursion
114
(if (slime-sprof-browser-line-expanded-p)
115
(slime-sprof-browser-collapse)
116
(slime-sprof-browser-expand))))))
117
118
(defun slime-sprof-browser-collapse ()
119
(let ((inhibit-read-only t))
120
(slime-sprof-browser-add-line-text-properties '(expanded nil))
121
(forward-line)
122
(loop until (or (eobp)
123
(get-text-property (point) 'profile-index))
124
do
125
(delete-region (point-at-bol) (point-at-eol))
126
(unless (eobp)
127
(delete-char 1)))))
128
129
(defun slime-sprof-browser-expand ()
130
(lexical-let* ((buffer (current-buffer))
131
(point (point))
132
(index (get-text-property point 'profile-index)))
133
(slime-eval-async `(swank:swank-sprof-expand-node ,index)
134
(lambda (data)
135
(with-current-buffer buffer
136
(save-excursion
137
(destructuring-bind (&key callers calls)
138
data
139
(slime-sprof-browser-add-expansion callers
140
"Callers"
141
0)
142
(slime-sprof-browser-add-expansion calls
143
"Calls"
144
0))))))))
145
146
(defun slime-sprof-browser-add-expansion (data type nesting)
147
(when data
148
(let ((inhibit-read-only t))
149
(slime-sprof-browser-add-line-text-properties '(expanded t))
150
(end-of-line)
151
(insert (format "\n %s" type))
152
(dolist (node data)
153
(destructuring-bind (index name cumul) node
154
(insert (format (format "\n%%%ds" (+ 7 (* 2 nesting))) ""))
155
(slime-insert-propertized
156
(slime-sprof-browser-name-properties)
157
(let ((len (- 59 (* 2 nesting))))
158
(format (format "%%-%ds " len)
159
(abbreviate-name name len))))
160
(slime-sprof-browser-add-line-text-properties
161
`(profile-sub-index ,index))
162
(insert (format "%6.2f" cumul)))))))
163
164
(defun slime-sprof-browser-line-expanded-p ()
165
(get-text-property (point) 'expanded))
166
167
(defun slime-sprof-browser-add-line-text-properties (properties)
168
(add-text-properties (point-at-bol)
169
(point-at-eol)
170
properties))
171
172
(defun slime-sprof-browser-name-properties ()
173
'(face sldb-restart-number-face))
174
175
;; "Go to function"
176
177
(defun slime-sprof-browser-go-to ()
178
(interactive)
179
(let ((sub-index (get-text-property (point) 'profile-sub-index)))
180
(when sub-index
181
(let ((pos (text-property-any
182
(point-min) (point-max) 'profile-index sub-index)))
183
(when pos (goto-char pos))))))
184
185
;; Disassembly
186
187
(defun slime-sprof-browser-disassemble-function ()
188
(interactive)
189
(let ((index (or (get-text-property (point) 'profile-index)
190
(get-text-property (point) 'profile-sub-index))))
191
(when index
192
(slime-eval-describe `(swank:swank-sprof-disassemble
193
,index)))))
194
195
;; View source
196
197
(defun slime-sprof-browser-view-source ()
198
(interactive)
199
(let ((index (or (get-text-property (point) 'profile-index)
200
(get-text-property (point) 'profile-sub-index))))
201
(when index
202
(slime-eval-async
203
`(swank:swank-sprof-source-location ,index)
204
(lambda (source-location)
205
(destructure-case source-location
206
((:error message)
207
(message "%s" message)
208
(ding))
209
(t
210
(slime-show-source-location source-location))))))))
211
212
(provide 'slime-sprof)
213
214