Open rbuchberger opened 10 months ago
Thank you for using this plugin, I don't have that typescript project which has the large codebase. I will try to investigate
Thanks! I'm pretty sure it's not specific to typescript, it just has to do with slow completion results. You can probably test with a well placed sleep function. Is it possible that some function is running synchronously when it should be async?
Just wanted to add that I'm experiencing the same issue regardless of filetype.
I noticed insert mode being lag immediately after trying this plugin. I have honza/vim-snippets
installed. Disabling it made things much better. But that means not having any packaged snippets to use.
Then I tried disabling just the snipmate support with ultisnip settings: let g:UltiSnipsEnableSnipMate = 0
.
And that seems to makes things much better as well, but still allows me to use
Could the lag be from having many snippets installed?
The reason is on this line: https://github.com/quangnguyen30192/cmp-nvim-ultisnips/blob/main/lua/cmp_nvim_ultisnips/source.lua#L27
function source.complete(self, _, callback)
local items = {}
local snippets = cmpu_snippets.load_snippets(self.expandable_only) -- -------------HERE
which then calls cmp_nvim_ultisnips#get_current_snippets
.
This is called so many times, on every single character. This is quite an inefficient implementation.
get_current_snippets
is an awfully stateful function, vim_helper.buf.line_till_cursor
reads the line until the cursor. It's even slower due to RPC. Instead, we can use cmp's completion context (see cmp.Context
) which already provides the completion string.
The snippet results can be cached as they usually do not change. We can reload the snippet data only when needed, e.g. reading only once when the buffer loads (and invalidate the cache when UltiSnip refreshes).
Or being asynchronous when loading the available snippet items would be another option.
Thanks for the heads up, that's a good suggestion. I'll try to make it great.
Thanks! Performance problems are non-trivial, but thanks for writing the great plugin. Please let me know if there's anything I can help you with. In my free cycle I will try to see if I can suggest more concrete ideas for improvement.
So, I was being bothered by this too, so I tried to take a look at this. But since I am not good at lua, I asked chatGPT. It came up with this solution, which works much faster:
function source.complete(self, _, callback)
local items = {}
-- Get all UltiSnips snippets for the current filetype
local snippets = vim.fn["UltiSnips#SnippetsInCurrentScope"]()
-- Iterate through each snippet and format it for nvim-cmp
for trigger, snippet in pairs(snippets) do
table.insert(items, {
label = trigger,
insertText = trigger,
kind = cmp.lsp.CompletionItemKind.Snippet,
documentation = {
kind = cmp.lsp.MarkupKind.Markdown,
value = snippet,
},
})
end
-- Invoke the callback with the completion items
callback({ items = items, isIncomplete = false })
end
function source.resolve(self, completion_item, callback)
callback(completion_item)
end
Did some editing to fix the issue with the description.
Hey guys, thanks for your patience when using this plugin. Most of you guys have experienced in this performance issue, this is quite tricky to fix because underneath, utilsnips is using python as a bridge to work with the snippet system. This is we can't fully control to make performance better in term of using throttling, debouncing or caching, particularly to this plugin itself.
However nvim cmp offers us several options we can try regarding the performance improvement https://github.com/hrsh7th/nvim-cmp/blob/main/doc/cmp.txt#L441C1-L472
cmp will serve as a proxy, that can do throttling or debouncing before accessing to the source of the snippet.
Please try and let me know
Thanks @cristobaltapia for your code (or your AI's code) but this is not enough sources which are also fetched from the snippet python API where the performance bottle neck is
Yes, I don't get the snippet for the preview, but I get the completions for the snippets and their description, which is enough for me at least. I'm looking forward for a better solution though (it is nice to have the snippet preview).
get_current_snippets is an awfully stateful function, vim_helper.buf.line_till_cursor reads the line until the cursor. It's even slower due to RPC. Instead, we can use cmp's completion context (see cmp.Context) which already provides the completion string.
@wookayin in a recent commit, I have moved the Python code to a separate file and reduced the "statefulness" of the function. While trying to implement your suggestion above, do you know how I could pass an arbitrary Lua string to a Python function with pyeval
? This is a place where the function is now called: https://github.com/quangnguyen30192/cmp-nvim-ultisnips/blob/f5c5cd6da094ef04a7d6e0bea73f71dfa5dde9bf/lua/cmp_nvim_ultisnips/snippets.lua#L17
Simply using string concatenation wouldn't work since the completion string could contain special characters like "
.
Hello! Firstly, thanks a ton for this awesome plugin. I use it every day to earn a living.
I'm having an issue very similar to this one in the main cmp repo: https://github.com/hrsh7th/nvim-cmp/issues/1608 Basically, when this plugin is enabled, typing in insert mode becomes slow and laggy. It's most noticeable with typescript files in big projects (Slow language server), but I can see a difference with simple rust files as well.
Asciinema recording: (Note the jumpiness when holding the 'a' key) -
My neovim config My cmp config specifically
Please let me know if I can do any more troubleshooting! Thanks.