unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Performance issue in project.el
       [not found] <20210627212123.xciejcjxrv2rxsra.ref@Ergus>
@ 2021-06-27 21:21 ` Ergus
  2021-06-28 11:42   ` Ergus
  0 siblings, 1 reply; 5+ messages in thread
From: Ergus @ 2021-06-27 21:21 UTC (permalink / raw)
  To: emacs-devel

Hi:

Using tramp I tried to use project.el with a command like
project-switch-to-buffer and it took like 10 minutes to complete.

I ran a profiler and I found that most of the time was taken by:

project-current called in a loop for all the opened buffers it calls
project--find-in-directory that calls
project-find-functions and there is going all the time.

I had global-tags-try-project-root (a function from an external package
tat call gnu global program... something like gtags). And I optimized
that function to use a cache and avoid calling the program for every
buffer creating a cache for it.

Something like:

```
(defvar global-tags--dbpath-cache (make-hash-table))

(cl-defun global-tags--get-dbpath (&optional (dir default-directory))
   "Filepath for database from DIR."
   (pcase (gethash dir global-tags--dbpath-cache)
     ('empty nil)
     ('nil
      (puthash dir 'empty global-tags--dbpath-cache)
      (when-let*
        === BLA ===
        (when (file-exists-p dbpath)
	 (puthash dir dbpath global-tags--dbpath-cache))))
     (code code)))
````

Now the time is half than before but still very slow to use the command
(around 3-5 minutes to complete) and running again the profiler I get this:

         5637  89% - command-execute
         5549  88%  - byte-code
         5549  88%   - project--read-project-buffer
         5549  88%    - let*
         5336  85%     - read-buffer
         5323  84%      - ivy-completing-read
         5323  84%       - ivy-read
         4941  78%        - ivy--reset-state
         4941  78%         - ivy--buffer-list
         4941  78%          - internal-complete-buffer
         4941  78%           - #<lambda -0x1a357caf01243d61>
         4941  78%            - and
         4941  78%             - equal
         4941  78%              - save-current-buffer
         4941  78%               - project-current
         4941  78%                - project--find-in-directory
         4548  72%                 - project-try-vc
         4537  72%                  - vc-responsible-backend
         4478  71%                   - #<compiled 0xd3f2e32af0966f7>
         4478  71%                    - vc-call-backend
         4478  71%                     - apply
         1470  23%                      + vc-svn-responsible-p
         1142  18%                      + vc-bzr-responsible-p
          970  15%                      + vc-hg-responsible-p
          390   6%                      + vc-git-responsible-p
          156   2%                      + vc-cvs-responsible-p
          126   2%                      + vc-rcs-responsible-p
          108   1%                      + vc-sccs-responsible-p
           98   1%                      + vc-src-responsible-p
           57   0%                   + tramp-file-name-handler
           11   0%                  + vc-file-getprop
          393   6%                 + global-tags-try-project-root
          375   5%        + read-from-minibuffer
           13   0%      + if
          213   3%     + project-current
           88   1%  + funcall-interactively
          572   9% + ...
           51   0% + timer-event-handler
            8   0% + redisplay_internal (C function)


As you can see most of the time is still taken by project-current and I
can't really understand why:

1) Are so many samples 4548 seems a very high number for only 25 opened
buffers.

2) why project-try-vc still takes so much...? Specially for unfrequent
vc systems in our days like svn or bzr that I am not using.

3) If vc-handled-backends has these value by default: '(RCS CVS SVN SCCS
SRC Bzr Git Hg Mtn) why is there some time taken by vc-hg-responsible-p
that is latter than git in the list?

In any case:

Maybe (I think I mentioned this before) `project.el` needs a sort of
cache to speedup some functions like `project-current` that are called
very frequently.

Best,
Ergus



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Performance issue in project.el
  2021-06-27 21:21 ` Performance issue in project.el Ergus
@ 2021-06-28 11:42   ` Ergus
  2021-06-28 12:14     ` Phil Sainty
  2021-06-28 14:10     ` Stefan Monnier
  0 siblings, 2 replies; 5+ messages in thread
From: Ergus @ 2021-06-28 11:42 UTC (permalink / raw)
  To: emacs-devel

On Sun, Jun 27, 2021 at 11:21:23PM +0200, Ergus wrote:
>Hi:
>
>Using tramp I tried to use project.el with a command like
>project-switch-to-buffer and it took like 10 minutes to complete.
>
>I ran a profiler and I found that most of the time was taken by:
>
>project-current called in a loop for all the opened buffers it calls
>project--find-in-directory that calls
>project-find-functions and there is going all the time.
>
>I had global-tags-try-project-root (a function from an external package
>tat call gnu global program... something like gtags). And I optimized
>that function to use a cache and avoid calling the program for every
>buffer creating a cache for it.
>
>Something like:
>
>```
>(defvar global-tags--dbpath-cache (make-hash-table))
>
>(cl-defun global-tags--get-dbpath (&optional (dir default-directory))
>  "Filepath for database from DIR."
>  (pcase (gethash dir global-tags--dbpath-cache)
>    ('empty nil)
>    ('nil
>     (puthash dir 'empty global-tags--dbpath-cache)
>     (when-let*
>       === BLA ===
>       (when (file-exists-p dbpath)
>	 (puthash dir dbpath global-tags--dbpath-cache))))
>    (code code)))
>````
>
>Now the time is half than before but still very slow to use the command
>(around 3-5 minutes to complete) and running again the profiler I get this:
>
>        5637  89% - command-execute
>        5549  88%  - byte-code
>        5549  88%   - project--read-project-buffer
>        5549  88%    - let*
>        5336  85%     - read-buffer
>        5323  84%      - ivy-completing-read
>        5323  84%       - ivy-read
>        4941  78%        - ivy--reset-state
>        4941  78%         - ivy--buffer-list
>        4941  78%          - internal-complete-buffer
>        4941  78%           - #<lambda -0x1a357caf01243d61>
>        4941  78%            - and
>        4941  78%             - equal
>        4941  78%              - save-current-buffer
>        4941  78%               - project-current
>        4941  78%                - project--find-in-directory
>        4548  72%                 - project-try-vc
>        4537  72%                  - vc-responsible-backend
>        4478  71%                   - #<compiled 0xd3f2e32af0966f7>
>        4478  71%                    - vc-call-backend
>        4478  71%                     - apply
>        1470  23%                      + vc-svn-responsible-p
>        1142  18%                      + vc-bzr-responsible-p
>         970  15%                      + vc-hg-responsible-p
>         390   6%                      + vc-git-responsible-p
>         156   2%                      + vc-cvs-responsible-p
>         126   2%                      + vc-rcs-responsible-p
>         108   1%                      + vc-sccs-responsible-p
>          98   1%                      + vc-src-responsible-p
>          57   0%                   + tramp-file-name-handler
>          11   0%                  + vc-file-getprop
>         393   6%                 + global-tags-try-project-root
>         375   5%        + read-from-minibuffer
>          13   0%      + if
>         213   3%     + project-current
>          88   1%  + funcall-interactively
>         572   9% + ...
>          51   0% + timer-event-handler
>           8   0% + redisplay_internal (C function)
>
>
>As you can see most of the time is still taken by project-current and I
>can't really understand why:
>
>1) Are so many samples 4548 seems a very high number for only 25 opened
>buffers.
>
>2) why project-try-vc still takes so much...? Specially for unfrequent
>vc systems in our days like svn or bzr that I am not using.
>
>3) If vc-handled-backends has these value by default: '(RCS CVS SVN SCCS
>SRC Bzr Git Hg Mtn) why is there some time taken by vc-hg-responsible-p
>that is latter than git in the list?
>
Just replying to myself about 3)

After reading the function vc-responsible-backend I can see that it uses
a mapcar to test the responsible; so all of them are always tested in
every single call every time.

As a workaround I removed all the uninteresting handlers from
vc-handled-backends and I get better times now, but IMHO it is still
very inefficient almost a minute for project-switch-to-buffer is
excessive.

VCS changing is not something that happens very often to require a check
of all the backends everytime, several times for every buffer in many
project.el functions right?

Should I open an issue for this?

Maybe it is possible to add a sort of optimization like the one
mentioned above to vc-responsible-backend?

Probably I am wrong, but: Do we really need to check all this everytime
we call project-current?  I mean, a file or default-dir changes project
so often that we need to check with all the backends constantly?

Either in the local system the performance penalty seems to be
significant.

>In any case:
>
>Maybe (I think I mentioned this before) `project.el` needs a sort of
>cache to speedup some functions like `project-current` that are called
>very frequently.
>
>Best,
>Ergus
>



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Performance issue in project.el
  2021-06-28 11:42   ` Ergus
@ 2021-06-28 12:14     ` Phil Sainty
  2021-06-28 12:44       ` Ergus
  2021-06-28 14:10     ` Stefan Monnier
  1 sibling, 1 reply; 5+ messages in thread
From: Phil Sainty @ 2021-06-28 12:14 UTC (permalink / raw)
  To: Ergus; +Cc: emacs-devel

On 2021-06-28 23:42, Ergus wrote:
> After reading the function vc-responsible-backend I can see that it 
> uses
> a mapcar to test the responsible; so all of them are always tested in
> every single call every time.

It didn't in Emacs 27, but see bug #42966 and commit 2697123933e3

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=42966

commit 2697123933e3ac7ed4e21a6d12746a98ed7fa74a
Author: Lars Ingebrigtsen <larsi@gnus.org>
Date:   Mon Oct 26 21:10:36 2020 +0100

     Make vc-responsible-backend choose the most specific backend

     * lisp/vc/vc.el (vc-responsible-backend): Search through all the
     VC backends instead of the first one, and choose the one that's
     most specific (bug#42966).




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Performance issue in project.el
  2021-06-28 12:14     ` Phil Sainty
@ 2021-06-28 12:44       ` Ergus
  0 siblings, 0 replies; 5+ messages in thread
From: Ergus @ 2021-06-28 12:44 UTC (permalink / raw)
  To: Phil Sainty; +Cc: emacs-devel

Reading the issue I see that there is already vc-file-prop-obarray.

Could vc-responsible-backend use that?

On Tue, Jun 29, 2021 at 12:14:57AM +1200, Phil Sainty wrote:
>On 2021-06-28 23:42, Ergus wrote:
>>After reading the function vc-responsible-backend I can see that it 
>>uses
>>a mapcar to test the responsible; so all of them are always tested in
>>every single call every time.
>
>It didn't in Emacs 27, but see bug #42966 and commit 2697123933e3
>
>https://debbugs.gnu.org/cgi/bugreport.cgi?bug=42966
>
>commit 2697123933e3ac7ed4e21a6d12746a98ed7fa74a
>Author: Lars Ingebrigtsen <larsi@gnus.org>
>Date:   Mon Oct 26 21:10:36 2020 +0100
>
>    Make vc-responsible-backend choose the most specific backend
>
>    * lisp/vc/vc.el (vc-responsible-backend): Search through all the
>    VC backends instead of the first one, and choose the one that's
>    most specific (bug#42966).
>



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Performance issue in project.el
  2021-06-28 11:42   ` Ergus
  2021-06-28 12:14     ` Phil Sainty
@ 2021-06-28 14:10     ` Stefan Monnier
  1 sibling, 0 replies; 5+ messages in thread
From: Stefan Monnier @ 2021-06-28 14:10 UTC (permalink / raw)
  To: Ergus; +Cc: emacs-devel

> Should I open an issue for this?

Yes, unless you find there's one for it already of course,


        Stefan




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-06-28 14:10 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20210627212123.xciejcjxrv2rxsra.ref@Ergus>
2021-06-27 21:21 ` Performance issue in project.el Ergus
2021-06-28 11:42   ` Ergus
2021-06-28 12:14     ` Phil Sainty
2021-06-28 12:44       ` Ergus
2021-06-28 14:10     ` Stefan Monnier

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).