nvim-tree / nvim-tree.lua

A file explorer tree for neovim written in lua
Other
7.17k stars 610 forks source link

Very slow on exit neovim #2438

Closed overcache closed 10 months ago

overcache commented 1 year ago

Description

I've noticed that when I exit Neovim, it's extremely slow, often hanging on the :qa command for 5 seconds or even longer before the Neovim instance finally quits. After individually removing plugins, I eventually identified that nvim-tree was the cause of this issue.

Neovim version

NVIM v0.9.2
Build type: Release
LuaJIT 2.1.0-beta3

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "/usr/local/Cellar/neovim/0.9.2/share/nvim"

Run :checkhealth for more info

Operating system and version

macOS12.1, Darwin macbox.local 21.2.0 Darwin Kernel Version 21.2.0: Sun Nov 28 20:28:54 PST 2021; root:xnu-8019.61.5~1/RELEASE_X86_64 x86_64

nvim-tree version

934469b

Clean room replication

vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1

vim.cmd [[set runtimepath=$VIMRUNTIME]]
vim.cmd [[set packpath=/tmp/nvt-min/site]]
local package_root = "/tmp/nvt-min/site/pack"
local install_path = package_root .. "/packer/start/packer.nvim"
local function load_plugins()
  require("packer").startup {
    {
      "wbthomason/packer.nvim",
      "nvim-tree/nvim-tree.lua",
      "nvim-tree/nvim-web-devicons",
      -- ADD PLUGINS THAT ARE _NECESSARY_ FOR REPRODUCING THE ISSUE
    },
    config = {
      package_root = package_root,
      compile_path = install_path .. "/plugin/packer_compiled.lua",
      display = { non_interactive = true },
    },
  }
end
if vim.fn.isdirectory(install_path) == 0 then
  print "Installing nvim-tree and dependencies."
  vim.fn.system { "git", "clone", "--depth=1", "https://github.com/wbthomason/packer.nvim", install_path }
end
load_plugins()
require("packer").sync()
vim.cmd [[autocmd User PackerComplete ++once echo "Ready!" | lua setup()]]
vim.opt.termguicolors = true
vim.opt.cursorline = true

-- MODIFY NVIM-TREE SETTINGS THAT ARE _NECESSARY_ FOR REPRODUCING THE ISSUE
_G.setup = function()
  require("nvim-tree").setup {
        -- copy form 'ahmedkhalf/project.nvim'
      sync_root_with_cwd = true,
      respect_buf_cwd = true,
      update_focused_file = {
        enable = true,
        -- update_root = true
      },
      --

      disable_netrw = true,
      view = { number = false, },
      git = { ignore = false },
      renderer = {
        add_trailing = true,
      },
      }
end

Steps to reproduce

  1. cd to some Project: cd webpack
  2. nvim -nu /tmp/nvt-min.lua
  3. open some file: :e package.json
  4. :NvimTreeFindFile
  5. open some file in deep dir: :e node_modules/semver/bin/semver.js
  6. quit: :qa, neovim will hang 3~5 seconds

Expected behavior

:qa execute then neovim quit quickly.

Actual behavior

quit: :qa, neovim will hang 3~5 seconds

gegoune commented 1 year ago

I can't replicate it (in sense that I have never experienced that before). Is the delay present without any open buffers as well?

overcache commented 1 year ago

I can't replicate it (in sense that I have never experienced that before). Is the delay present without any open buffers as well?

when I delete all buffer manually before exit, the issuse still present. Did you use the 'webpack' project? When I open files in node_modules, the issuse occur. Open other files which not in node_modules, thats fine.

overcache commented 1 year ago

https://github.com/nvim-tree/nvim-tree.lua/assets/1908329/994f4775-3ebe-4325-aa0d-7322799e14c0

alex-courtis commented 1 year ago

Tried unsuccessfully with minimal config and linux source: :e COPYING :NvimTreeFindFile :e tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h

Your video shows that you are using plugins other than specified in the minimal config. Please reproduce with the minimal config as instructed: "Clean Room" Replication

Please enable Diagnostic Logging after reproducing with git profile and watcher.

overcache commented 1 year ago

There is no other plugins, the top line of video was the tmux panel list.

I tried to reproduce on a fresh linux virtual machine this morning but failed. It seems that I can only replay the issue on my iMac.

After delete some nvim-tree setting, the necessary settting are:

  require("nvim-tree").setup {
      update_focused_file = {
        enable = true,
      },
      git = { ignore = false },
   }

Either set update_focused_file.enable = false or git.ignore = true get rid of the "hang on :qa" problem. I can't find out what environment effect nvim-tree works, any advice?

Here is another video:

https://github.com/nvim-tree/nvim-tree.lua/assets/1908329/07985944-5138-45b3-bb0b-8e08b52153ae

alex-courtis commented 1 year ago

Is the iMac old / slow? Was the VM on that iMac?

It seems the issue could be:

  1. slow git processing (unlikely, as it's mostly async)
  2. slow FS enumeration

Diagnostic Logging will shed some light on this.

alex-courtis commented 1 year ago

Unrelated, however you can get some significant OSX git performance gains Git fsmonitor Daemon

overcache commented 1 year ago
iShot_2023-10-02_15 28 19

My computer is a 2017 iMac. It's a bit old, but not that old. I just logged into the guest account and was able to reproduce the issue. I'll try it on my M1 MacBook at home tonight.

overcache commented 1 year ago

I can reproduce on M1 Macbook air(macOS 12.6.5 ) too.

alex-courtis commented 1 year ago

Without logs or being able to reproduce there's no path forward here.

@gegoune could you attempt a replication?

GZLiew commented 1 year ago

I can reproduce this and neovim just hangs after I did a npm install on the project I think nvim-tree is trying to read updates in node_modules folder which causes the hang

gegoune commented 1 year ago

@alex-courtis Didn't get a chance yet. node_modules consist of thousands of files. Maybe adding it to gitignore will help? Since │nvim-tree.git.timeout is lower by default than reported 5s I am not sure how it is related. Also, what is git.ignore? Can't find it in docs nor code.

alex-courtis commented 1 year ago

@alex-courtis Didn't get a chance yet. node_modules consist of thousands of files.

Maybe adding it to gitignore will help? Since │nvim-tree.git.timeout is lower by default than reported 5s I am not sure how it is related.

This looks like #1931 The combination of gitignore and the MacOS git fs monitor daemon worked in that case.

Also, what is git.ignore? Can't find it in docs nor code.

Ah... that one was silently migrated to filters.git_ignored

Raised #2468 as it may be unrelated.

alex-courtis commented 1 year ago

We need logs (see above) to continue @overcache , @GZLiew

GZLiew commented 1 year ago

@alex-courtis ignoring node_modules fixes the latency of closing nvim but other editors didnt have this issue before heres the logs and video https://github.com/nvim-tree/nvim-tree.lua/assets/43195293/adc04760-677c-4d3d-8545-edd73ba0851a

{ actions = { change_dir = { enable = true, global = false, restrict_above_cwd = false }, expand_all = { exclude = {}, max_folder_discovery = 300 }, file_popup = { open_win_config = { border = "shadow", col = 1, relative = "cursor", row = 1, style = "minimal" } }, open_file = { eject = true, quit_on_open = true, resize_window = true, window_picker = { chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", enable = true, exclude = { buftype = { "nofile", "terminal", "help" }, filetype = { "notify", "packer", "qf", "diff", "fugitive", "fugitiveblame" } }, picker = "default" } }, remove_file = { close_window = true }, use_system_clipboard = true }, auto_reload_on_write = true, diagnostics = { debounce_delay = 50, enable = false, icons = { error = "", hint = "", info = "", warning = "" }, severity = { max = 1, min = 4 }, show_on_dirs = false, show_on_open_dirs = true }, disable_netrw = false, experimental = {}, filesystem_watchers = { debounce_delay = 50, enable = true, ignore_dirs = {} }, filters = { custom = {}, dotfiles = false, exclude = {}, git_clean = false, git_ignored = true, no_buffer = false }, git = { disable_for_dirs = {}, enable = true, show_on_dirs = true, show_on_open_dirs = true, timeout = 400 }, hijack_cursor = false, hijack_directories = { auto_open = true, enable = true }, hijack_netrw = true, hijack_unnamed_buffer_when_opening = false, live_filter = { always_show_folders = true, prefix = "[FILTER]: " }, log = { enable = true, truncate = false, types = { all = true, config = false, copy_paste = false, dev = false, diagnostics = false, git = false, profile = false, watcher = false } }, modified = { enable = false, show_on_dirs = true, show_on_open_dirs = true }, notify = { absolute_path = true, threshold = 2 }, on_attach = <function 1>, prefer_startup_root = false, reload_on_bufenter = false, renderer = { add_trailing = false, full_name = false, group_empty = false, highlight_bookmarks = "none", highlight_clipboard = "name", highlight_diagnostics = false, highlight_git = false, highlight_modified = "none", highlight_opened_files = "none", icons = { bookmarks_placement = "signcolumn", diagnostics_placement = "signcolumn", git_placement = "before", glyphs = { bookmark = "󰆤", default = "", folder = { arrow_closed = "", arrow_open = "", default = "", empty = "", empty_open = "", open = "", symlink = "", symlink_open = "" }, git = { deleted = "", ignored = "◌", renamed = "➜", staged = "✓", unmerged = "", unstaged = "✗", untracked = "★" }, modified = "●", symlink = "" }, modified_placement = "after", padding = " ", show = { bookmarks = true, diagnostics = true, file = true, folder = true, folder_arrow = true, git = true, modified = true }, symlink_arrow = " ➛ ", web_devicons = { file = { color = true, enable = true }, folder = { color = true, enable = false } } }, indent_markers = { enable = false, icons = { bottom = "─", corner = "└", edge = "│", item = "│", none = " " }, inline_arrows = true }, indent_width = 2, root_folder_label = ":~:s?$?/..?", special_files = { "Cargo.toml", "Makefile", "README.md", "readme.md" }, symlink_destination = true }, respect_buf_cwd = false, root_dirs = {}, select_prompts = false, sort = { files_first = false, folders_first = true, sorter = "name" }, sync_root_with_cwd = false, system_open = { args = {}, cmd = "" }, tab = { sync = { close = false, ignore = {}, open = false } }, trash = { cmd = "trash" }, ui = { confirm = { remove = true, trash = true } }, update_focused_file = { enable = true, ignore_list = {}, update_root = false }, view = { centralize_selection = false, cursorline = true, debounce_delay = 15, float = { enable = false, open_win_config = { border = "rounded", col = 1, height = 30, relative = "editor", row = 1, width = 30 }, quit_on_focus_loss = true }, number = true, preserve_window_proportions = false, relativenumber = true, side = "left", signcolumn = "yes", width = 200 } }

overcache commented 1 year ago

We need logs (see above) to continue @overcache , @GZLiew

here it is: nvim-tree.log

steps which genrate logs above:

  1. cd webpack
  2. nvim -nu ~/Downloads/nvt-min.lua
  3. :e package.json
  4. :NvimTreeFindFile
  5. :e node_modules/semver/bin/semver.js
  6. :qa
alex-courtis commented 1 year ago

This is useful, thank you for digging.

It looks like it's simply the number of folders. Let's fix #2468 and see how it goes.

gegoune commented 11 months ago

https://github.com/nvim-tree/nvim-tree.lua/issues/2468 has been resolved.

@overcache Would you mind updating nvim-tree to check if issue still persists?

overcache commented 11 months ago

2468 has been resolved.

@overcache Would you mind updating nvim-tree to check if issue still persists?

still persists with 05f55c1

nvim-tree.log

nvt-min.lua.txt

Shougo commented 11 months ago

I think your neovim is debug mode. Please check.

https://github.com/neovim/neovim/issues/18670

overcache commented 11 months ago

I think your neovim is debug mode. Please check.

neovim/neovim#18670

no, it's not.

❯ nvim --version
NVIM v0.9.4
Build type: Release
LuaJIT 2.1.1700008891

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "/opt/homebrew/Cellar/neovim/0.9.4/share/nvim"

Run :checkhealth for more info

checkhealth.txt

Shougo commented 11 months ago

Hm... It is only for nvim-tree? I don't know it is nvim-tree's problem or not. You can check where the routine causes the problem. It is OSS.

GZLiew commented 10 months ago

@overcache this was actually an easy fix for me

I digged into the source and found

local function is_folder_ignored(path)
  for _, folder in ipairs(IGNORED_PATHS) do
    if vim.startswith(path, folder) then
      return true
    end
  end

  for _, ignore_dir in ipairs(M.config.filesystem_watchers.ignore_dirs) do
    if vim.fn.match(path, ignore_dir) ~= -1 then
      return true
    end
  end

  return false
end

so all I had to add in my config was

  filesystem_watchers = {
    enable = true,
    debounce_delay = 50,
    ignore_dirs = {
      "node_modules"
    },
  },

and now my nvim instantly closes without any delay

GZLiew commented 10 months ago

@alex-courtis I guess this is a feature request whether we can add gitignore to config filesystem_watchers instead of specifying all the directories as I still want to view the ignored files in nvim-tree but do not want them to be actively watched

alex-courtis commented 10 months ago

That sounds reasonable.

Yes, we can add .gitignore parsing and filtering, however it is a non-trivial task, with no off the shelf solution: #2367

I'll close this one as we can track it in there.

overcache commented 10 months ago

@overcache this was actually an easy fix for me

I digged into the source and found

local function is_folder_ignored(path)
  for _, folder in ipairs(IGNORED_PATHS) do
    if vim.startswith(path, folder) then
      return true
    end
  end

  for _, ignore_dir in ipairs(M.config.filesystem_watchers.ignore_dirs) do
    if vim.fn.match(path, ignore_dir) ~= -1 then
      return true
    end
  end

  return false
end

so all I had to add in my config was

  filesystem_watchers = {
    enable = true,
    debounce_delay = 50,
    ignore_dirs = {
      "node_modules"
    },
  },

and now my nvim instantly closes without any delay

thanks, it works