Yevgnen / ivy-rich

More friendly interface for ivy.
364 stars 37 forks source link

ivy-rich-switch-buffer-root performance is pretty ugly #93

Closed s-kostyaev closed 3 years ago

s-kostyaev commented 3 years ago

Hi! Thanks for this cool project. Unfortunately I can't switch buffer with long buffer list if I use ivy-rich with default settings. I need to disable a couple of transformers. Before I did it, go to next line in ivy-switch-buffer can spend seconds. This is screenshot of profiler-report:

Emacsa9l1Sr

Yevgnen commented 3 years ago

How many buffers did you open? Did you open any remote buffer over tramp?

s-kostyaev commented 3 years ago

190 buffers are open. No one from tramp. Most buffers from 2 projects, and several from couple other projects.

Yevgnen commented 3 years ago

That's quite a lot...

I tested in 300+ buffers with multiple projects (org notes, Python projects) and haven't encountered the issue. All of projectile, ffip and project.el work well. Are you using the master version of ivy-rich? Do you have complicate project structures? Does this happen with a small number of buffers opened?

s-kostyaev commented 3 years ago

Are you using the master version of ivy-rich?

I use 20201118.16 version

Does this happen with a small number of buffers opened?

No. Looks like it start to be as slow as many buffers with project.el git project (vc-project) are opened. I use only project.el for project management.

Do you have complicate project structures?

What project structures are complicated? I have many files deep nested in project directories. Is it complicated enough?

Yevgnen commented 3 years ago

projectile has trouble dealing with complicate project structures but can be relieved by customizing projectile-project-root-files-functions. I might take some time to see what I can do with project.el.

LogicalOverflow commented 3 years ago

I also have a noticeable (but not that big) delay with (just) 30 buffers, most of them in no project, when calling ivy-switch-buffer/switching lines. As I use ivy-switch-buffer very often, I want it to be fast and that delay did bug me.

I did some hacking on-top of ivy-rich-swich-buffer-root and added:

(setq ivy-rich-switch-buffer-root-cache (make-hash-table :test 'equal))

(defun ivy-rich-switch-buffer-root (candidate)
  (when-let* ((dir (ivy-rich--switch-buffer-directory candidate)))
    (let ((cached-value (gethash dir ivy-rich-switch-buffer-root-cache 'not-found)))
      (if (not (eq cached-value 'not-found)) cached-value
        (let ((value
               (unless (or (and (file-remote-p dir)
                                (not ivy-rich-parse-remote-buffer))
                           ;; Workaround for `browse-url-emacs' buffers , it changes
                           ;; `default-directory' to "http://" (#25)
                           (string-match "https?://" dir))
                 (cond ((bound-and-true-p projectile-mode)
                        (let ((project (or (ivy-rich--local-values
                                            candidate 'projectile-project-root)
                                           (projectile-project-root dir))))
                          (unless (string= project "-")
                            project)))
                       ((require 'find-file-in-project nil t)
                        (let ((default-directory dir))
                          (ffip-project-root)))
                       ((require 'project nil t)
                        (when-let ((project (project-current nil dir)))
                          (car (project-roots project))))))))
          (puthash dir value ivy-rich-switch-buffer-root-cache)
          value)))))

This works well for now and the switching buffers is fast again. I think caching these results is a reasonable thing to do, as a file switching projects shouldn't happen often, right?

I would be happy to make a PR for this, if you don't mind. But there are few things I would also do:

If you have any more suggestions, please let me know.

s-kostyaev commented 3 years ago

I don't use ivy such as ivy-rich anymore. But this solution looks reasonable.