doomemacs / doomemacs

An Emacs framework for the stubborn martian hacker
MIT License
19.4k stars 3.05k forks source link

SPC SPC is very slow in Flutter projects when (ivy +icons) is enabled #3718

Closed thiagokokada closed 3 years ago

thiagokokada commented 4 years ago

What did you expect to happen? SPC SPC (+ivy/projectile-find-file) to be fast.

What actually happened? It is very slow, taking multiple seconds to open. Even after opening it, just navigating between files is slow too, taking many seconds to go from the first file in the list to the second file, for example.

The repository that this problem is occurring is very big. This is the result of a git status:

$ time git status                                   
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
git status  0.30s user 0.17s system 131% cpu 0.355 total

Since it is so big, we have multiple packages (sub-directories) that we work, and for each package that we work we generally add a .projectile file so we don't index the whole repository at once. This used to work well enough and this repository didn't used to be slow to navigate, but now it is almost impossible.

Additional details:

If an error message is involved include a backtrace of it.

How to acquire a backtrace:
https://github.com/hlissner/doom-emacs/blob/develop/docs/getting_started.org#how-to-extract-a-backtrace-from-an-error

Steps to reproduce:

  1. Get a big repository, add a .projectile in a sub-directory
  2. Run SPC SPC on it

System information:

``` emacs version 27.1 features XPM JPEG TIFF GIF PNG RSVG CAIRO SOUND DBUS GSETTINGS GLIB NOTIFY INOTIFY LIBSELINUX GNUTLS LIBXML2 FREETYPE HARFBUZZ M17N_FLT LIBOTF ZLIB TOOLKIT_SCROLL_BARS GTK3 X11 XDBE XIM MODULES THREADS LIBSYSTEMD JSON PDUMPER GMP build ago 10, 2020 buildopts (--prefix=/nix/store/h9k95mz9jlcv6dmrx315rh6nlw2zrczv-emacs-unstable-emacs-27.1-rc2 --disable-build-details --with-modules --with-x-toolkit=gtk3 --with-xft --with-cairo CFLAGS=-DMAC_OS_X_VERSION_MAX_ALLOWED=101200) windowsys x daemonp server-running doom version 2.0.9 build HEAD -> develop, origin/develop, origin/HEAD 8bbac4bfb 2020-08-08 03:06:26 -0400 dir ~/.dotfiles/doom-emacs/.config/doom/ system type gnu/linux config x86_64-pc-linux-gnu shell /run/current-system/sw/bin/zsh uname Linux 5.7.14 #1-NixOS SMP Fri Aug 7 07:33:11 UTC 2020 x86_64 path (/nix/store/1aiwad27kcpjma7ywa543pgkygz21c7b-emacs-packages-deps/bin ~/.local/bin ~/dev/nu/mini-meta-repo/monocli/bin ~/dev/nu/nucli.py/bin ~/dev/nu/ios-cli ~/dev/nu/nucli ~/dev/nu/nudev ~/.npm-packages/bin ~/.go/bin ~/.config/emacs/bin /nix/store/g5n9pfb4lna781l395axpgbsnwh74dqr-kitty-0.16.0/bin /nix/store/maiqgyf438l41fnxwdy4p0jf6ai501ki-imagemagick-6.9.10-71/bin /nix/store/029dn7y8g6vfzwnvk9rmadvsvjy8zzqg-xsel-unstable-2019-08-21/bin /nix/store/84g84bg47xxg01ba3nv0h418v5v3969n-ncurses-6.1-20190112-dev/bin /run/wrappers/bin ~/.nix-profile/bin /etc/profiles/per-user/thiagoko/bin /nix/var/nix/profiles/default/bin /run/current-system/sw/bin ~/sdk-flutter/bin/cache/dart-sdk/bin ~/sdk-flutter/bin /nix/store/h9k95mz9jlcv6dmrx315rh6nlw2zrczv-emacs-unstable-emacs-27.1-rc2/libexec/emacs/27.1/x86_64-pc-linux-gnu) config envfile nil elc-files 0 modules (:completion company (ivy +fuzzy +icons) :ui doom hl-todo (modeline +light) ophints (popup +defaults) treemacs vc-gutter vi-tilde-fringe workspaces :editor (evil +everywhere) file-templates fold (format +onsave) multiple-cursors word-wrap :emacs (dired +icons) electric undo vc :term vterm :checkers syntax :tools docker (eval +overlay) lookup lsp magit :lang cc (clojure +lsp) data (dart +flutter +lsp) elixir emacs-lisp (go +lsp) hy json markdown nim nix org plantuml (python +poetry) (ruby +rails) rust scala sh yaml :config (default +bindings +smartparens)) packages ((adoc-mode) (clj-refactor :disable t) (evil-escape :disable t) (lispyville) (lsp-ui :disable t) (sort-words)) unpin (n/a) elpa (vterm) ```
thiagokokada commented 4 years ago

So I discovered that removing +icons from ivy fixed the issue. This should be an issue with all-the-icons-ivy maybe :thinking: ?

Edit: also disabling +icons from dired since I found a similar performance issue on it.

thiagokokada commented 4 years ago

Maybe I hit this bug since I recently enabled Cairo? https://github.com/nix-community/emacs-overlay/pull/53

thiagokokada commented 4 years ago

I discovered that the issue was probably +icons from seeing that in the root of this repository the performance was better than in a directory with .projectile file inside this repository because SPC SPC didn't show any icons at root.

So my analysis of the issue:

hlissner commented 4 years ago

Since it is so big, we have multiple packages (sub-directories) that we work, and for each package that we work we generally add a .projectile file so we don't index the whole repository at once. This used to work well enough and this repository didn't used to be slow to navigate, but now it is almost impossible.

Is it still indexing the submodules despite the .projectile files? If so, try using an .ignore file in the base repo with the submodules listed in them. e.g.

submodule1/
submodule2/
submodule3/
thiagokokada commented 4 years ago

Is it still indexing the submodules despite the .projectile files? If so, try using an .ignore file in the base repo with the submodules listed in them. e.g.

I don't think this is the issue since I moved one of the submodule to a directory outside of the Git repository to test and still saw the same issue. So this is why I am thinking this is not related to the size of repository anymore, but something related to either Dart (since this is a Flutter project) or GraphQL.

hlissner commented 4 years ago

I don't think this is the issue since I moved one of the submodule to a directory outside of the Git repository to test and still saw the same issue. So this is why I am thinking this is not related to the size of repository anymore, but something related to either Dart (since this is a Flutter project) or GraphQL.

Did you remember to invalidate the cache after moving the submodule? (M-x projectile-invalidate-cache or SPC p i)

Nevermind. Forgot you've turned projectile-enable-caching off.

EDIT: Oh, but did you restart Emacs, at least (it still has an in-memory cache iirc)?

thiagokokada commented 4 years ago

@hlissner Just tested it again, making sure that projectile-enable-caching was set to nil and in a fresh instance of Emacs opened directly in the submodule (without a Git repository). Same issue.

profile.el.zip

thiagokokada commented 4 years ago

So it seems to be an issue with Flutter/Dart projects. I attach a simple Flutter project created with flutter create ahhhh.

Set (ivy +icons) and (dired +icons) in init.el (maybe also (dart +flutter)?), unzip this project and open it in Emacs, do a SPC SPC and press and hold C-j so between the files in the list. See that the Emacs will become very slow.

ahhhh.zip

P.S.: This is not an issue with other kind of repositories. I tried to do the same with a bigger repository (compared to this ahhhh project) in Clojure and works fine.

hlissner commented 4 years ago

Perhaps it's a font issue. Are there any missing or generic icons? If all-the-icons-ivy doesn't specify an icon for a filetype, then it might fallback on a generic icon (typically unicode), and Emacs can really struggle to display those for some fonts.

hlissner commented 4 years ago

ahhhh.zip

Seems fine for me. Try changing your font. I'm using JetBrains Mono atm.

thiagokokada commented 4 years ago

I tried to use the default Doom font, same issue. Also, it doesn't seem to be missing any icons.

I do think it is related to either Cairo or Harfbuzz. @hlissner do you have both of them compiled with your Emacs?

hlissner commented 4 years ago

I have harfbuzz, but not cairo. I'll ask around the Discord for other cairo users.

I tried to use the default Doom font

Could you try a different, but explicitly determined font? Doom's "default" font is your system font, and there's no telling if that font is any different from the one you normally use, or is another incompatible font. Testing Fira Code would be a safe bet.

hlissner commented 4 years ago

Error during redisplay: (eval (propertize (let ((buffer-file-name (buffer-file-name (buffer-base-buffer)))) (or (when (and (not (file-remote-p buffer-file-name)) buffer-file-name) (if-let (project (doom-project-root buffer-file-name)) (let ((filename (or buffer-file-truename (file-truename buffer-file-name)))) (file-relative-name filename (concat project ".."))))) "%b")) 'face (cond ((buffer-modified-p) '(error bold mode-line-buffer-id)) ((+modeline-active) 'mode-line-buffer-id)) 'help-echo buffer-file-name)) signaled (wrong-type-argument stringp nil)

Side note: I fixed this error yesterday. Please update and see if, perhaps, that error was causing the slowness.

thiagokokada commented 4 years ago

Could you try a different, but explicitly determined font? Doom's "default" font is your system font, and there's no telling if that font is any different from the one you normally use, or is another incompatible font. Testing Fira Code would be a safe bet.

Tried Fira Code, same issue.

Edit: I set it like this:

(setq doom-font (font-spec :family "Fira Code" :size 18)
      doom-big-font-increment 2
      doom-unicode-font (font-spec :family "Noto Sans Mono"))
polaris64 commented 4 years ago

From what I can tell this appears to be an issue with Dart files, specifically when ivy-rich-mode is enabled. Perhaps it has something to do with the icon displayed for Dart files (a capital "E" inside a box)?

I also get extreme slowdown whenever Ivy displays a completion list containing a Dart file while ivy-rich-mode is enabled. Disabling this mode (still using Ivy) solves the problem.

I ran a profile and I can see that most of the CPU time is spent resizing the minibuffer: -

- command-execute                                                                              1759  98%
 - call-interactively                                                                          1759  98%
  - funcall-interactively                                                                      1759  98%
   - counsel-find-file                                                                         1757  98%
    - counsel--find-file-1                                                                     1757  98%
     - ivy-read                                                                                1757  98%
      - read-from-minibuffer                                                                   1754  98%
       - redisplay_internal (C function)                                                        694  38%
        - ivy--window-size-changed                                                              693  38%
           ivy--resize-minibuffer-to-fit                                                        693  38%
        + eval                                                                                    1   0%
       - ivy--queue-exhibit                                                                     691  38%
        - ivy--exhibit                                                                          691  38%
         - ivy--insert-minibuffer                                                               691  38%
            ivy--resize-minibuffer-to-fit                                                       691  38%
       + minibuffer-inactive-mode                                                                 1   0%
       + timer-event-handler                                                                      1   0%
      + ivy--reset-state                                                                          1   0%

I was going to try to find out what this icon is and how Emacs is rendering it, but I'm not sure how to get the contents of the minibuffer during the Ivy operation into another buffer so that I can investigate it further. Does anyone have any ideas how to do this?

polaris64 commented 4 years ago

Further to the above, I wrote some Elisp which extracts the contents of the minibuffer and inserts it into the current buffer together with all text properties.

It's definitely a problem with the display of the "E" icon. Scrolling in this buffer is incredibly slow (3-4s just for the point to move one position). As soon as I delete the offending "E" character, everything goes back to normal in that buffer.

I ran describe-char on this icon and got the following: -

             position: 321 of 1494 (21%), column: 0
            character: TAB (displayed as TAB) (codepoint 9, #o11, #x9)
              charset: ascii (ASCII (ISO646 IRV))
code point in charset: 0x09
               script: latin
               syntax:      which means: whitespace
             to input: type "C-x 8 RET 9" or "C-x 8 RET CHARACTER TABULATION"
          buffer code: #x09
            file code: #x09 (encoded by coding system utf-8-unix)
              display: by display table entry [?› ? ] (see below)

The display table entry is displayed by these fonts (glyph codes):
›: ftcrhb:-ADBO-Source Code Pro-normal-normal-normal-*-12-*-*-*-m-0-iso10646-1 (#x3A4)
    : -- no font --

Character code properties: customize what to show
  old-name: CHARACTER TABULATION
  general-category: Cc (Other, Control)

There is an overlay here:
 From 321 to 461
  face                 hl-line
  priority             -50
  window               #<window 224 on read-minibuffer.el>

There are text properties here:
  display              [Show]
  face                 whitespace-tab
  fontified            t
  mouse-face           ivy-minibuffer-match-highlight
  read-only            nil

Expanding the display text property shows: -

#("" 0 1
  (rear-nonsticky t display
                  (raise -0.24)
                  font-lock-face
                  (:family "file-icons" :height 1.2 :inherit all-the-icons-blue)
                  face
                  (:family "file-icons" :height 1.2 :inherit all-the-icons-blue)))

(the glyph here is 0xE698)

Looking at the output of describe-char, it appears that my system does not have a font capable of displaying this glyph properly as it says "-- no font --". So I'm assuming this is the root of the problem, as suggested by @hlissner above.

I checked all-the-icons.el/data/data-fileicons.el and, sure enough, all-the-icons-data/file-icon-alist maps "dart" to 0xE698.

To work around this problem, I added the following to my config: -

(after! all-the-icons
  (add-to-list 'all-the-icons-data/file-icon-alist '("dart" . "D")))
polaris64 commented 4 years ago

Looks like it is related to this issue: https://github.com/domtronn/all-the-icons.el/issues/225

It appears that the designated glyph 0xE698 is not part of the file-icons.ttf font

github-actions[bot] commented 3 years ago

This issue has been automatically marked stale because of a lack of recent activity. If this issue is still valid, reply to it or remove the label or it will be closed in 7 days.