Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Profiling shell commands in Emacs

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.

like image 946
fredefox Avatar asked May 21 '19 09:05

fredefox


People also ask

How do I run a shell command in Emacs?

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.

How do I get shells in Emacs?

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.

How do I run a shell script in Emacs?

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 ).

What is Emacs command in Linux?

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.

How do I run a subshell from an Emacs buffer?

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.

What is Eshell in Emacs?

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.


Video Answer


1 Answers

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)
like image 164
martin_joerg Avatar answered Nov 15 '22 17:11

martin_joerg