vim multiple gopls

多个 gopls daemon 导致内存耗尽

问题及现象

在 vim 中打开大项目(比如 kubernetes)时会导致系统内存被耗尽,最终导致整台电脑死机。其根本的原因是 vim 中配置的各种插件(比如 vim-go、coc.nvim、coc-go、ycm等)都会各自启动一个 gopls serve daemon 进程,如下图所示:

g01

每个 gopls serve daemon 进程都会消耗 2-4G 的内存,甚至更多(对于更大的项目),如下图:

g02

对上述现象 go 团队及社区给出的解释可参考。go 团队启动 gopls serve daemon 时会基于lsp 空间,不同 lsp 空间彼此独立以方便启动多个 daemon 来满足特殊场景的测试/开发等,而 lsp 空间最终会根据 TMPDIR 的目录来具体实现,因此可理解为如果两个 gopls 指定 TMPDIR 目录不相同时将会启动两个不同的 gopls serve daemon 进程。而对于 vim-go、coc.nvim/coc-go 等插件其内部获取 TMPDIR 的方式不一样,得到的 TMPDIR 也不一样(可参考),因此会启动多个 gopls serve daemon 进程,最终导致内存耗尽。

解决方案

为了避免 vim 中多个插件开启多个 gopls serve daemon 进程,可通过使多个插件共享同一个 gopls serve daemon 的方式来减少内存消耗。具体有如下方案:

  • 方案一:向 go 团队提交 issue,说明原因后由 go 团队最终解决。社区已有人向 go 团队反馈
  • 方案二:可通过修改 coc.nvim,coc-go 等插件获取 TMPDIR 的结果来指定多个插件共享同一个 gopls,但这种方式需要修改插件的代码源码。可参考
  • 方案三:修改 coc.nvim,coc-go 的配置文件,这种方式比较方便处理。可参考

修改 coc.nvim 的配置:

  • 官方原始配置,通过在 coc-setting.json 指定 language server

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    {
    "languageserver": {
    "golang": {
    "command": "gopls",
    "args": ["-remote=auto"],
    "rootPatterns": ["go.mod", ".vim/", ".git/", ".hg/"],
    "filetypes": ["go"]
    }
    }
    }

    这个配置文件会有两个问题:

    • 会导致多个插件有多个 gopls sever daemon 进程,即使加上 -remote=auto 多个插件并不会共享同一个 gopls 进程,因为插件使用的 TMPDIR 目录不一样。

    • 在开发过程中,使用代码自动补全时会出现多余的重复选项(如图03),这个问题我是后来才发现的,当不添加 languageserver 的配置时不会有重复的选项(如图04)。

      gp03 gp04

  • 我的 coc.nvim/coc-go 的最终配置为 cos-setting.json:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    {
    "go.goplsArgs": ["-remote=auto", "-logfile", "/tmp/gopls-cocvim.log"], // 指定 remote=auto, coc.nvim 的 TMPDIR 与 gopls 的在同一个文件夹下
    "go.goplsPath": "/home/qingwei/go/bin/gopls" // 指定共享的 gopls 二进制文件,注意:如果只修改 TMPDIR 也不行,必须使用同一个 gopls 二进制文件启动才能共享同一个 serve daemon。
    "go.goplsOptions": {
    // go 多个module 嵌套问题:
    // https://github.com/golang/tools/blob/master/gopls/doc/workspace.md
    // https://github.com/josa42/coc-go
    "experimentalWorkspaceModule": true
    }
    }

    最终效果如下:
    gp05
    gp06

参考:


vim multiple gopls
https://qingwei8.github.io/2021/08/12/vim-2021-08-12-vim-multiple-gopls/
作者
qingwei
发布于
2021年8月12日
许可协议