Closed TeoDev1611 closed 3 years ago
I just found this solution but if if have other idea ππΌ https://github.com/TeoDev1611/AstroVim/blob/astro/lua/plugins.lua#L99
Hm what exactly is being profiled here? All I see is just numbers! In my next todo I was actually planning on taking a look at performance and loading times, so would be interesting to know what exactly happens inside "nvim-lsp-installer config"
Is the nvim-lsp-installer plugin and config @williamboman the numbers are the startup time of the plugin
So no interactions with any Lua APIs? Just neovim loading the plugin itself? I have profiled that particular scenario before and there is no bottlenecks that would cause a 100ms load time (it's consistently one of my fastest plugins to load, averaging <0.04ms
). Are you sure you're not calling on_server_ready()
or get_installed_servers()
etc? These are highly i/o-bound and I'd not be surprised if they produce such high numbers
No this use some functions and configurations:
local lsp_installer = require 'nvim-lsp-installer'
local lsp_servers = require 'nvim-lsp-installer.servers'
local M = {}
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require('cmp_nvim_lsp').update_capabilities(capabilities)
-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
local on_attach = function(client, bufnr)
local function buf_set_keymap(...)
vim.api.nvim_buf_set_keymap(bufnr, ...)
end
local function buf_set_option(...)
vim.api.nvim_buf_set_option(bufnr, ...)
end
-- Enable completion triggered by <c-x><c-o>
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
-- Mappings.
local opts = { noremap = true, silent = true }
-- See `:help vim.lsp.*` for documentation on any of the below functions
buf_set_keymap('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
buf_set_keymap('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
buf_set_keymap('n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', opts)
buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
buf_set_keymap('n', '<space>ca', '<cmd>lua vim.lsp.buf.code_action()<CR>', opts)
buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
buf_set_keymap('n', '<space>e', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
buf_set_keymap('n', '[d', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
buf_set_keymap('n', ']d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', opts)
buf_set_keymap('n', '<space>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', opts)
buf_set_keymap('n', '<space>f', '<cmd>lua vim.lsp.buf.formatting()<CR>', opts)
end
local function setup_handlers()
vim.lsp.handlers['textDocument/publishDiagnostics'] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
virtual_text = {
spacing = 5,
prefix = '',
},
signs = false, -- rely on highlight styles instead, don't want to clobber signcolumn
})
end
function M.setup()
setup_handlers()
vim.cmd [[ command! LspLog tabnew|lua vim.cmd('e'..vim.lsp.get_log_path()) ]]
local ok, sumneko_lua = lsp_servers.get_server 'sumneko_lua'
if ok then
if not sumneko_lua:is_installed() then
sumneko_lua:install()
end
end
lsp_installer.on_server_ready(function(server)
local opts = {
on_attach = on_attach,
capabilities = capabilities,
}
if server.name == 'eslintls' then
opts.settings = {
format = { enable = true },
}
end
server:setup(opts)
vim.cmd [[ do User LspAttachBuffers ]]
end)
end
return M
Ah and with the configuration shown above takes this:
Yeah the heavy stuff is actually scheduled already, so just measuring that code it'll be blazing fast :P. I'm currently experimenting a bit with speeding up the parts that are scheduled
So I've done some work to defer require
calls as much as possible. These are by far the biggest culprits in terms of performance. On my Windows machine a single require
took ~5ms π€’ (multiply that for each available server...). The problem today is that all the metadata for a given server exist exclusively inside each server's Lua module - which forces us to require
all servers to do things like identify which ones are installed etc. I've started separating this a bit and colocating all the essential metadata in one location, and deferring all the "ad-hoc" metadata to the server modules themselves. This allows us to very quickly identify which servers are installed by scanning the root install directory once (via libuv), and then only require
the installed servers.
The important metric is what's called when a user registers a on_server_ready
callback, because that's the first touchpoint. Here are some profiling results I did across 3 different machines and operating systems:
macOS (11 servers installed)
37ms -> 10ms (~73% faster)
macOS (1 server installed)
37ms -> 1ms (~97% faster)
Windows (11 servers installed)
230ms -> 48ms (~80% faster)
Low-end Ubuntu machine (11 servers installed)
80ms -> 24ms (~70% faster)
I went a bit too far down the rabbit hole however and started looking at some other unrelated things at the same time (which resulted in for example https://github.com/neovim/neovim/issues/15648). Now it's all tangled together, will have to do work to extract the parts that are not ready yet π. What makes this all more difficult is that I want to maintain backwards compatibility (for custom servers), which sometimes complicates things
:o that's interesting i have a idea is possible call only one server when y call a lua function this could be make the startup time more faster like this:
:lua require('nvim-lsp-installer.lazy').load('sumneko_lua')
or something like this but can be have a setup option for if donΒ΄t want call to the server manually can be made this automatically example:
require('nvim-lsp-installer').setup{
lazy = {
enable = true
}
}
False by default for disable de lazy loading :p
No need to make this opt-in behavior (would probably be a headache to even implement two different code paths in the first place)! It'll be default going forward, just finishing up the last bits and pieces at the moment
:lua require('nvim-lsp-installer.lazy').load('sumneko_lua')
This is pretty much what will happen - although it will be internalized in a non-public module
@TeoDev1611 Would you mind trying out the io-speedups-new
branch (https://github.com/williamboman/nvim-lsp-installer/pull/93) and see if it runs fine for you?
Yeaaaaaaah This amazing works
Re: https://github.com/neovim/neovim/issues/15648 I have looked into it, I just haven't decided what to do about it yet :)
Re: neovim/neovim#15648 I have looked into it, I just haven't decided what to do about it yet :)
Hey! Thanks for the update! I posted another comment with how I could imagine things working in https://github.com/neovim/neovim/issues/15648.
Lazy loading added in #93
Hi π I'm here again
I just found this with the plugi takes sooome of time any idea how improve the lazy loading?