Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory Usage Issue With Certain Completions #1039

Open
2 tasks done
Xemptuous opened this issue Jan 19, 2025 · 11 comments
Open
2 tasks done

Memory Usage Issue With Certain Completions #1039

Xemptuous opened this issue Jan 19, 2025 · 11 comments
Labels
bug Something isn't working

Comments

@Xemptuous
Copy link

Make sure you have done the following

  • Updated to the latest version of blink.cmp
  • Searched for existing issues and documentation (try <C-k> on https://cmp.saghen.dev)

Bug Description

I am encountering this issue specifically with Zig's LSP (zls), and I am unsure if it happens in other instances.

I will be coding as usual, but then some completions (specifically related to the std.fs.File.* completions (such as open() or close()) will sometimes cause my neovim to freeze, RAM will go up by ~6GiB, and then after ~30 seconds, neovim will resume.

Sometimes, the memory drops back down to usual, and remains good for a while until I restart neovim. Other times, blink will continue to use all that ram, and it will be unusably slow and laggy until a restart, after which this problem sometimes happens, and sometimes doesn't; it's very unpredictable.

I am not sure what causes this, but it's definitely getting in the way enough to make it unusable for long coding sessions, atleast in Zig.

Relevant configuration

sources = { default = { "lsp", "path", "snippets", "buffer" } },
keymap = { preset = "super-tab" },
signature = { enabled = false },
fuzzy = { use_typo_resistance = false },
keyword = { range = "full" },
trigger = { show_in_snippet = false },
accept = { auto_brackets = { enabled = true } },

neovim version

v0.11.0-dev-1574+gac3859a441

blink.cmp version

2144c58

@Xemptuous Xemptuous added the bug Something isn't working label Jan 19, 2025
Saghen added a commit that referenced this issue Jan 19, 2025
@Saghen
Copy link
Owner

Saghen commented Jan 19, 2025

I'm not familiar with Zig so a repro.lua and example file (or project, if the Zig LSP requires it), would be quite helpful

@Xemptuous
Copy link
Author

I managed to get a repro.lua working that reproduces the exact issue predictably.

The main culprit seems to be nvim-treesitter/nvim-treesitter with TSInstall zig.

The specific issue is caused by selecting or attempting to scroll "through" the close() method on a file specifically while the documentation is showing.

I am not having this issue with nvim-cmp, so I assumed it was related specific to blink.cmp

Here is a minimal main.zig file I am using that causes the leak:

const std = @import("std");

fn main() !void {
    const f = try std.fs.cwd().openFile("input.txt", .{});
    // typing `f.l`, waiting for docs to show, then scrolling down to `close()`
}

along with the repro.lua:

-- Run with `nvim -u repro.lua`
vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()

---@diagnostic disable-next-line: missing-fields
require("lazy.minit").repro({
    spec = {
        {
            "saghen/blink.cmp",
            build = "cargo build --release",
            event = { "InsertEnter", "CmdlineEnter" },
            opts = {
                completion = {
                    documentation = {
                        auto_show = true,
                    },
                },
            },
        },
        {
            "neovim/nvim-lspconfig",
            opts = {
                servers = {
                    zls = {},
                },
            },
            config = function(_, opts)
                local lspconfig = require("lspconfig")
                for server, config in pairs(opts.servers) do
                    -- passing config.capabilities to blink.cmp merges with the capabilities in your
                    -- `opts[server].capabilities, if you've defined it
                    config.capabilities = require("blink.cmp").get_lsp_capabilities()
                    lspconfig[server].setup(config)
                end
            end,
        },
        {
            "nvim-treesitter/nvim-treesitter",
            opts = { ensure_installed = { "zig" } },
            config = function(_, opts) require("nvim-treesitter.configs").setup(opts) end,
        },
    },
})

@NicoElbers
Copy link
Contributor

NicoElbers commented Jan 21, 2025

I experience the same issue:

> nvim --version
NVIM v0.11.0-nightly+2b07b14
Build type: Release
LuaJIT 2.1.1713773202
Run "nvim -V1 -v" for more info

> zig version
0.14.0-dev.2837+f38d7a92c

> zls --version
0.14.0-dev

minimal.lua:

vim.api.nvim_create_autocmd("FileType", {
	pattern = "zig",
	callback = function()
		vim.lsp.start({
			name = "zls",
			cmd = { "zls" },
			root_dir = nil,
			settings = vim.empty_dict(),
		})
	end,
})

vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()

require("lazy.minit").setup({
	spec = {
		{
			"saghen/blink.cmp",
			version = "*",
			opts = {},
		},
	},
})

bug.zig:

const std = @import("std");
const File = std.fs.File;
File.

Now going to the last line, typing "cl" should freeze up the editor.

Edit: Also reproduces with zig 0.14.0-dev.2182+54d0ba418 and zls 0.14.0-dev.
zls annoying shows no commit, but I can verify that it was on commit 1b319502d91cba8e15e46379b57354c716b75b4e (commited november 7th)

I am thus fairly confident that a ZLS change is not at fault

@NicoElbers
Copy link
Contributor

Digging further still, I got this stack trace from lldb, stopping while the memory leak/ freeze was happening:

* thread #1, name = 'nvim', stop reason = signal SIGSTOP
  * frame #0: 0x000079b50e8978f6 libtree-sitter.so.0.24`___lldb_unnamed_symbol261 + 6
    frame #1: 0x000079b50e8a146f libtree-sitter.so.0.24`___lldb_unnamed_symbol301 + 303
    frame #2: 0x000079b50e8a6b00 libtree-sitter.so.0.24`ts_parser_parse + 10640
    frame #3: 0x0000000000652d30 nvim`parser_parse.lto_priv.0 + 640
    frame #4: 0x000079b50e797a46 libluajit-5.1.so.2`___lldb_unnamed_symbol458 + 7350
    frame #5: 0x000079b50e7fa0bd libluajit-5.1.so.2`lua_pcall + 189
    frame #6: 0x000000000064cb2b nvim`nlua_schedule_event + 155
    frame #7: 0x00000000007a9d98 nvim`state_handle_k_event + 120
    frame #8: 0x000000000050e745 nvim`insert_execute.lto_priv.0 + 5205
    frame #9: 0x00000000007b0721 nvim`state_enter + 273
    frame #10: 0x0000000000877bf9 nvim`insert_enter.constprop.0 + 793
    frame #11: 0x00000000006cf77e nvim`invoke_edit.lto_priv.0 + 478
    frame #12: 0x00000000006bfdf4 nvim`normal_execute.lto_priv.0 + 2900
    frame #13: 0x00000000007b0789 nvim`state_enter + 377
    frame #14: 0x00000000006bc534 nvim`normal_enter + 132
    frame #15: 0x000000000045b7d6 nvim`main + 4982
    frame #16: 0x000079b50e42a1fc libc.so.6`__libc_start_call_main + 124
    frame #17: 0x000079b50e42a2b9 libc.so.6`__libc_start_main@@GLIBC_2.34 + 137
    frame #18: 0x000000000045d675 nvim`_start + 37
(lldb)

This seems to indicate some problem with treesitter, but if it's in treesitter or in blink's interaction with treesitter I don't know

@Saghen
Copy link
Owner

Saghen commented Jan 21, 2025

Does the issue occur without treesitter enabled for drawing? I believe LazyVim enables it by default. completion.menu.draw.treesitter = {}

@NicoElbers
Copy link
Contributor

NicoElbers commented Jan 21, 2025

I don't set it in my own config, but setting it explicitly to that resolves the issue

Edit: I was looking in the wrong place

@Saghen
Copy link
Owner

Saghen commented Jan 21, 2025

Thanks, like you said, it seems likely this is an issue with treesitter's zig parser rather than with blink.cmp, but it's possible we're using the API incorrectly. It may make sense to open an issue in the treesitter repo if you're able to find a reproduction

@NicoElbers
Copy link
Contributor

I'll have a look, thank you :)

@NicoElbers
Copy link
Contributor

Correction, I was wrong. I had downgraded my entire configuration about a month, and there it worked. Applying this fix does not fix the issue

@NicoElbers
Copy link
Contributor

I think I have found a workaround:

Setting:
completion.documentation.treesitter_highlighting,
signature.window.treesitter_highlighting

both to false, seems to resolve my issue, at the cost of course of nice colored docs. Maybe this gives you an indication as to what's going on @Saghen ?

@NicoElbers
Copy link
Contributor

I have found that this line, called from here is to blame.

If I were to hazard a guess, it's a problem with the zig treesitter parser as you mentioned as well, since it seems somewhat out of date. That still doesn't explain the explosion of memory and maxing a core for 30 seconds, but that's an investigation for not 1 AM.

As a workaround for anyone experiencing the same, I have this fork which applies this patch, disabling tree-stitter highlighting when a File is at all involved:

diff --git a/lua/blink/cmp/lib/window/docs.lua b/lua/blink/cmp/lib/window/docs.lua
index f250701..8f75571 100644
--- a/lua/blink/cmp/lib/window/docs.lua
+++ b/lua/blink/cmp/lib/window/docs.lua
@@ -50,6 +50,12 @@ function docs.render_detail_and_documentation(opts)
   vim.api.nvim_buf_clear_namespace(opts.bufnr, highlight_ns, 0, -1)
 
   if #detail_lines > 0 and opts.use_treesitter_highlighting then
+    if vim.bo.filetype == 'zig' then
+      local lines = vim.api.nvim_buf_get_lines(opts.bufnr, 0, #detail_lines, false)
+
+      if lines[1] and string.find(lines[1], 'File') then return end
+    end
+
     docs.highlight_with_treesitter(opts.bufnr, vim.bo.filetype, 0, #detail_lines)
   end
 
@@ -83,8 +89,12 @@ function docs.highlight_with_treesitter(bufnr, filetype, start_line, end_line)
   local success, trees = pcall(vim.treesitter.get_parser, bufnr, root_lang)
   if not success or not trees then return end
 
+  -- The freeze happened after this line
+
   trees:parse({ start_line, end_line })
 
+  -- The freeze happened before this
+
   trees:for_each_tree(function(tree, tstree)
     local lang = tstree:lang()
     local highlighter_query = vim.treesitter.query.get(lang, 'highlights')

I won't make a PR of this, as the workaround is quite ridiculous and not even near the root cause. I'll see if I can get a repro in treesitter somewhere this week or next week

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants