I'm trying to profile the usually excellent find-things-fast
package to figure out why it's slow in my project.
I started profiling with profiler-start
, executed the command that's slow (ftf-find-file
), then immediately ran profiler-report
.
This generated the following report:
Functions CPU samples %
- command-execute 1770 88%
- call-interactively 1770 88%
- apply 1770 88%
- call-interactively@ido-cr+-record-current-command 1770 88%
- apply 1770 88%
- #<subr call-interactively> 1770 88%
- funcall-interactively 1770 88%
- ftf-find-file 1597 80%
- ftf-project-files-alist 1522 76%
- ftf-project-files-hash 1330 66%
- let 1330 66%
- mapcar 1330 66%
- #<lambda 0x5458e8e0> 1024 51%
- let* 1008 50%
cons 24 1%
+ split-string 282 14%
+ maphash 192 9%
+ ido-completing-read 67 3%
+ next-line 75 3%
+ ido-switch-buffer 41 2%
+ ido-switch-buffer-other-window 38 1%
+ profiler-report 19 0%
+ ... 145 7%
+ redisplay_internal (C function) 37 1%
+ timer-event-handler 26 1%
undefined 5 0%
+ gui-set-selection 4 0%
internal-echo-keystrokes-prefix 2 0%
The profiler report seems to blame the let*
function within ftf-project-files-hash
.
However, looking at that function:
(defun ftf-project-files-hash ()
"Returns a hashtable filled with file names as the key and "
(let ((default-directory (ftf-project-directory))
(table (make-hash-table :test 'equal)))
(mapcar (lambda (file)
(let* ((file-name (file-name-nondirectory file))
(full-path (expand-file-name file))
(pathlist (cons full-path (gethash file-name table nil))))
(puthash file-name pathlist table)))
(split-string (ftf-project-files-string)))
table))
It seems incredibly unlikely that let*
is the slow part, but rather one of the functions called within that let*
.
Why is profiler-report
stopping at let*
rather than telling me which component of that let*
is slow? How can I dig deeper to find which exactly function is slow?
mapcar
section to see how big the list is, e.g.,(message "length: %s" (length (split-string (ftf-project-files-string))))
. It may be that you are just dealing with a lot of stuff that needs to be processed. It may also be that the function itselfftf-project-files-string
is time consuming, and you might want to put ameasure-time
wrapper around it. See: https://stackoverflow.com/questions/23622296/emacs-timing-execution-of-function-calls-in-emacs-lisp – lawlist Aug 15 '18 at 17:36measure-time
macro throws the result of whatever it wraps (but I could be wrong), and themapcar
needs the result offtf-project-files-string
via (split-string ...). Thus, you may want to put a separatemeasure-time
statement with(measure-time (ftf-project-files-string))
before themapcar
statement to do some debugging. Of course, the profiler would then show double the time because that function would be called twice -- however, it is just for debugging to get a sense of the time cost. – lawlist Aug 15 '18 at 17:46