Skip to content

Better async#57

Merged
Kaiser-Yang merged 15 commits into
Kaiser-Yang:masterfrom
TheLeoP:better-async
May 4, 2025
Merged

Better async#57
Kaiser-Yang merged 15 commits into
Kaiser-Yang:masterfrom
TheLeoP:better-async

Conversation

@TheLeoP

@TheLeoP TheLeoP commented May 1, 2025

Copy link
Copy Markdown
Contributor

Problem:

The plugin isn't truly async everywhere. There are calls for sync on a plenary job that call vim.wait under the hood, which blocks the editor until the jobs has finished it's execution. This may not be a problem in unix-like systems, but it is in Windows.

This, plus the fact that the plugin delays the execution of this jobs until InsertEnter results in Neovim being blocked for a couple of seconds on InsertEnter the first time after opening Neovim.

Solution:

Ditch the plenary.nvim dependency altogether and use the builtin vim.system and lua coroutines to have async code everywhere.

As a consequence of this change I also ended up removing the async config option and defaulting to using async always (since there is no cost to doing so).

I would also prefer to eagerly start the cache related jobs earlier, but didn't change the code to do so because that's not my decision to make. Since they are async, they won't block the user in any case. This will allow the plugin to always offer completions results on insert mode, even when defaulting to async always.

@Kaiser-Yang

Kaiser-Yang commented May 2, 2025

Copy link
Copy Markdown
Owner

Actually, you can not async everywhere. In neovim, you can only be async when calling vim.system or something to create a new process, any lua code in the neovim is sync. Using plenary is to avoid the callback hell, in this plugin, it sems that using plenary or not are both OK, because this plugin is simple enough.

In the original code, I tried to make all the time consuming jobs async, there jobs are mainly fetching resources from internet. The jobs using sync should be executed very quickly, such as git log, it actually block the neovim, but you should not feel it, can you give a more specific explanation of the blocking in Windows? Is the repository really huge?

Coroutine is a good way to write code for this plugin, but this actually not solve the problem you mentioned. Or if i misunderstand something, can you give a more detailed explanation?

Comment thread lua/blink-cmp-git/init.lua Outdated
Comment thread lua/blink-cmp-git/init.lua Outdated
Comment thread lua/blink-cmp-git/init.lua Outdated
Comment thread lua/blink-cmp-git/init.lua
Comment thread lua/blink-cmp-git/init.lua Outdated
Comment thread lua/blink-cmp-git/types.lua Outdated
Comment thread lua/blink-cmp-git/init.lua Outdated
Comment thread lua/blink-cmp-git/utils.lua Outdated
Comment thread lua/blink-cmp-git/utils.lua
@TheLeoP

TheLeoP commented May 2, 2025

Copy link
Copy Markdown
Contributor Author

Actually, you can not async everywhere. In neovim, you can only be async when calling vim.system or something to create a new process, any lua code in the neovim is sync.

I know. Maybe my word choice wasn't the best. This PR makes all calls to external process async, it completely avoids the user of any blocking vim.wait.

Using plenary is to avoid the callback hell, in this plugin, it sems that using plenary or not are both OK, because this plugin is simple enough.

I know. But it's not necessary. Under the hood, plenary uses lua coroutines to avoid callback hell with luv. This PR does the same while removing the dependency on plenary.nvim.

In the original code, I tried to make all the time consuming jobs async, there jobs are mainly fetching resources from internet. The jobs using sync should be executed very quickly, such as git log, it actually block the neovim, but you should not feel it, can you give a more specific explanation of the blocking in Windows? Is the repository really huge?

It was not a huge repo, it was happening on my nvim-config repo and only on windows. Git it's just that much slower in windows, it has nothing to do with the repo size. The same repository on a unix-like system felt instantaneous, which means that making the code sync shouldn't be a problem in those cases and it's a win-win situation.

Coroutine is a good way to write code for this plugin, but this actually not solve the problem you mentioned. Or if i misunderstand something, can you give a more detailed explanation?

It does. That's how plenary (or any lua plugin's async code) works under the hood. It removes the dependency in plenary.nvim and, using it everywhere there are external processes being executed, stops Neovim from being blocked.

You can take a look at this post to learn more about how coroutines work with Neovim's async code: https://gregorias.github.io/posts/using-coroutines-in-neovim-lua/

TheLeoP added 7 commits May 2, 2025 07:46
Always create a cache when initializing source or when the previous
cache is invalidated. In completion, check if the cache is available. If
it is, use it. If it is not, asynchronously wait for it to be available.
@TheLeoP

TheLeoP commented May 2, 2025

Copy link
Copy Markdown
Contributor Author

I implemented the changes you requested. Let me know if you would like me to modify anything else. I could rebase the commits into a single one if you prefer after your review.

Comment thread lua/blink-cmp-git/types.lua Outdated
Comment thread lua/blink-cmp-git/init.lua
Comment thread lua/blink-cmp-git/utils.lua Outdated
Comment thread lua/blink-cmp-git/default/init.lua Outdated
@TheLeoP TheLeoP requested a review from Kaiser-Yang May 4, 2025 01:04
@Kaiser-Yang Kaiser-Yang merged commit 59c19ac into Kaiser-Yang:master May 4, 2025
1 check failed
@Kaiser-Yang

Copy link
Copy Markdown
Owner

Nice work!

Thank you very much!

@TheLeoP TheLeoP deleted the better-async branch May 4, 2025 16:26
@Kaiser-Yang

This comment was marked as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants