Skip to content

Slowdown with large files due to locality map #1841

@dyfrgi

Description

@dyfrgi

FAQ

  • I have checked the FAQ and it didn't resolve my problem.

Announcement

Minimal reproducible full config

This is your default suggested repro as this reproduces in the default config. That said, this also reproduces with an even more minimal config where the only completion source is path. My original repro was https://github.com/dyfrgi/slowcmp/blob/main/slowcmp.lua (based on the config from LazyVim) but I included your preferred vimscript init here as well.

if has('vim_starting')
  set encoding=utf-8
endif
scriptencoding utf-8

if &compatible
  set nocompatible
endif

let s:plug_dir = expand('/tmp/plugged/vim-plug')
if !filereadable(s:plug_dir .. '/plug.vim')
  execute printf('!curl -fLo %s/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim', s:plug_dir)
end

execute 'set runtimepath+=' . s:plug_dir
call plug#begin(s:plug_dir)
Plug 'hrsh7th/nvim-cmp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/vim-vsnip'
Plug 'neovim/nvim-lspconfig'
call plug#end()
PlugInstall | quit

" Setup global configuration. More on configuration below.
lua << EOF
local cmp = require "cmp"
cmp.setup {
  snippet = {
    expand = function(args)
      vim.fn["vsnip#anonymous"](args.body)
    end,
  },

  mapping = {
    ['<CR>'] = cmp.mapping.confirm({ select = true })
  },

  sources = cmp.config.sources({
    { name = "nvim_lsp" },
    { name = "buffer" },
  }),
}
EOF

lua << EOF
local capabilities = require('cmp_nvim_lsp').default_capabilities()

require'lspconfig'.cssls.setup {
  capabilities = capabilities,
}
EOF

Description

When editing a file with very long lines, starting editing is slow. This appears to be due to regexes running inside compare.locality, based on my profiling.

Steps to reproduce

Open a file with a very long line, e.g. https://github.com/dyfrgi/slowcmp/blob/main/slow-lhs.ini.
Start inserting

Expected behavior

It should start editing promptly

Actual behavior

It's slow, taking about 15 seconds to enter insert mode

Additional context

I think this also affects quit time.

I wasn't able to get a very good profile of this - for some reason these cmp functions don't show up in the built-in :profile logs, and building neovim with luajit compiled with -DLUAJIT_USE_PERFTOOLS still only gets me limited information. Maybe I'm using :profile wrong - if there's a good way to get this, I would love to know what it is. I tried starting nvim without opening the file, then running :profile start prof.log :profile file * :profile func *, opening the file with :e slow-lhs.ini, and then closing the file. Unfortunately it always winds up showing almost nothing from nvim-cmp in the log.

That said, I have some informal samples of stacks from hitting ctrl-c when noticing it was slow, and they were always this stack:

E5108: Error executing lua ...ocal/share/nvim/lazy/nvim-cmp/lua/cmp/config/compare.lua:161: couldn't parse regex: Keyboard interrupt
stack traceback:
	[C]: in function 'regex'
	...ocal/share/nvim/lazy/nvim-cmp/lua/cmp/config/compare.lua:161: in function 'callback'
	.../.local/share/nvim/lazy/nvim-cmp/lua/cmp/utils/cache.lua:38: in function 'ensure'
	...ocal/share/nvim/lazy/nvim-cmp/lua/cmp/config/compare.lua:159: in function 'update'
	...tenburg/.local/share/nvim/lazy/nvim-cmp/lua/cmp/init.lua:327: in function <...tenburg/.local/share/nvim/lazy/nvim-cmp/lua/cmp/init.lua:324>
	...ocal/share/nvim/lazy/nvim-cmp/lua/cmp/utils/feedkeys.lua:47: in function <...ocal/share/nvim/lazy/nvim-cmp/lua/cmp/utils/feedkeys.lua:45>

I'm not sure what is getting fed into it, since it seems a little odd for it to always pop out on the compile of the regex rather than the match. I have about 10 samples from hitting ctrl-c, which should be enough to see other stacks if they're common. When looking at the output from perf, I see about 50% of the time spent on __memcpy_avx_unaligned_erms, and then actually inside nvim I see a bunch of time spent on regex_match_line and vim_regexec_multi;bt_regexec_both;regtry;regrepeat;utfc_ptr2len. It's 9.3% at the top of that and 8% at the bottom, so it's spending a ton of time just iterating through the string.

At any rate, it's slow, and I don't know exactly why because I'm a neovim profiling noob.

By way of comparison, if I use a config which omits locality from the list of sorting comparators such as https://github.com/dyfrgi/slowcmp/blob/main/cmp-fast.vim, the issue no longer reproduces.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions