Is there a way to profile the amount of time blocking on shell commands in emacs? Consider the following program:
(profiler-start 'cpu)
(shell-command "sleep 3")
(profiler-report)
(profiler-stop)
The profiler report will look something like this:
- command-execute 371 95%
- call-interactively 371 95%
- funcall-interactively 329 84%
- execute-extended-command 175 44%
- execute-extended-command--shorter 157 40%
- completion-try-completion 149 38%
- completion--nth-completion 149 38%
- completion--some 143 36%
- #<compiled 0x438307f1> 143 36%
- completion-pcm-try-completion 102 26%
- completion-pcm--find-all-completions 98 25%
completion-pcm--all-completions 98 25%
+ completion-pcm--merge-try 4 1%
completion-basic-try-completion 41 10%
+ sit-for 16 4%
- eval-expression 154 39%
- eval 154 39%
- profiler-start 154 39%
- debug 154 39%
- recursive-edit 141 36%
- command-execute 114 29%
- call-interactively 114 29%
- byte-code 107 27%
+ read--expression 64 16%
+ read-extended-command 43 11%
+ funcall-interactively 7 1%
+ byte-code 42 10%
+ ... 19 4%
As you can see the time spent is more or less evenly distributed. I'm interested in seeing output that tells me that I'm spending the significant part of the program blocking on the shell-command sleep 3
, is this possible somehow? I am aware that sleep 3
is not heavy on my CPU - but I'm trying to figure out which shell commands are called from magit
that is taking such a long time - so I'll also be interested in stuff that's IO-bound.
You can execute an external shell command from within Emacs using ` M-! ' ( 'shell-command' ). The output from the shell command is displayed in the minibuffer or in a separate buffer, depending on the output size.
You can start an interactive shell in Emacs by typing M-x shell . By default, this will start the standard Windows shell cmd.exe . Emacs uses the SHELL environment variable to determine which program to use as the shell.
Emacs has commands for passing single command lines to shell subprocesses, and for running a shell interactively with input and output to an Emacs buffer, and for running a shell in a terminal emulator window. Run the shell command cmd and display the output ( shell-command ).
Emacs has commands for passing single command lines to shell subprocesses, and for running a shell interactively with input and output to an Emacs buffer, and for running a shell in a terminal emulator window.
Run the shell command cmd with region contents as input; optionally replace the region with the output ( shell-command-on-region ). Run the shell command cmd asynchronously, and display the output ( async-shell-command ). Run a subshell with input and output through an Emacs buffer.
M-x eshell invokes a shell implemented entirely in Emacs. It is documented in its own manual. See Eshell in Eshell: The Emacs Shell . How to run one shell command and return. Permanent shell taking input via Emacs. Special Emacs commands used with permanent shell. Two ways to recognize shell prompts.
Note that profiler.el
is a sampling profiler. You might want to try an instrumenting profiler such as elp.el
if you are interested in the wall time.
In your case you may want to instrument magit
by using M-x elp-instrument-package
RET magit
RET. After running your magit commands you can then take a look at the results using M-x elp-results
RET.
For magit
you would probably find that the function magit-process-file
is taking up a lot of time. To further investigate the specific function calls you could then simply instrument that or any other function by adding an advice function logging the runtime together with the function's arguments to the messages buffer for each individual function call as follows.
(defun log-function-time (f &rest args)
(let ((time-start (current-time)))
(prog1
(apply f args)
(message "%s seconds used in (magit-process-file %s)"
(time-to-seconds (time-subtract (current-time) time-start))
args))))
(advice-add 'magit-process-file :around 'log-function-time)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With