Pyls and jedi-language-server 100% CPU usage

I’m using the latest version of python-language-server.
It is very slow, taking seconds to show hoverdoc or highlight.

I have disabled all pyls plugins, and when testing just vim.lsp.buf.document_highlight(), it sometimes takes around 5-10 seconds and I can see my CPU load jump to nearly 100% while it hangs.

jedi-language-server is the same.

This can be reproduced for me on code as simple as:

import pandas as pd
df = pd.DataFrame()
df.merge()

and trying to invoke the highlight function on merge().

Other modules like hover (when I enable it) do the same thing.

How do I debug this? Pyright doesn’t have this issue.

Do you still have this problem in a clean venv? I use Jedi Language Server all the time and haven’t had any problems.

I used Pipx to install it.

Yes, jedi-language-server installed with pipx also behaves the same way.

What happens if you create a totally clean venv?

python3 -m venv ./temp-env
source ./temp-env/bin/activate
nvim foo.py

The issue is only apparent after I import a library like pandas.

python-language-server isn’t good. I’ve just had the same problem for years, I can only recommend you to use pyright instead.

Have you tried uninstalling the Palantir language server entirely and only using Jedi language server? I too had serious performance problems with the Palantir language server. But I’ve never encountered a problem like that with the Jedi language server.

Yes, jedi-language-server in an isolated env (via pipx) has the issue. Can you confirm that hover doc is fast for pandas for you?

Right, but I like to have options.

Both jedi-language-server and pyls are very slow, unfortunately (they’re both powered by jedi, which is the culprit here). There’s actually an option to have jedi skip analysis of some modules, and you may want to enable that for slow modules (it’s called auto_import_modules: Settings — Jedi 0.18.0 documentation)

The jedi-language-server readme has instructions on how to set jedi settings: GitHub - pappasam/jedi-language-server: A Python language server exclusively for Jedi. If Jedi supports it well, this language server should too.

2 Likes

Thanks. That’s very discouraging, turns out our options for a fast Python language server are very limited - it’s basically just down to pyright.

Regarding jedi-language-server configuration, am I correct in assuming I’d need to pass the “initializationOptions” dict to the “settings” parameter in lspconfig setup?

init_options and settings are separate keys in the call to .setup{}

1 Like

Thanks. That’s actually one of the most confusing parts about lspconfig - the auto-generated server docs are not helpful a lot of the time. Maybe this could be better documented.

So is it init_options and not initializationOptions? If so, why?

Yes, it’s init_options, it’s not documented (in nvim-lspconfig, it is in :help lsp), maybe it should be. We use snake_case over camelCase for most variable names, and the naming predates me.

Can someone, please post valid jedi_language_server config in lua format. I’ve tried different variables but none of the settings actually work.

return {
    flags = {
        allow_incremental_sync = true,
    },
    single_file_support = true,
    settings = {
        diagnostics = {
            enable = false,
        },
        initialization_options = {
            enable = false,
            diagnostics = {
                enable = false,
            },
            workspace = {
                symbols = {
                    ignore_folders = {
                        ".nox",
                        ".tox",
                        ".venv",
                        "__pycache__",
                        "venv",
                    },
                },
            },
        },
    },

Please start topics instead of necroing.

require("lspconfig").jedi_language_server.setup({
	init_options = {
		codeAction = {
			nameExtractVariable = 'jls_extract_var',
			nameExtractFunction = 'jls_extract_def',
		},
		completion = {
			disableSnippets = false,
			resolveEagerly = false,
			ignorePatterns = {},
		},
		diagnostics = {
			enable = true,
			didOpen = true,
			didChange = true,
			didSave = true,
		},
		hover = {
			enable = true,
			disable = {
				class = { all = false, names = {}, fullNames = {} },
				["function"] = { all = false, names = {}, fullNames = {} },
				instance = { all = false, names = {}, fullNames = {} },
				keyword = { all = false, names = {}, fullNames = {} },
				module = { all = false, names = {}, fullNames = {} },
				param = { all = false, names = {}, fullNames = {} },
				path = { all = false, names = {}, fullNames = {} },
				property = { all = false, names = {}, fullNames = {} },
				statement = { all = false, names = {}, fullNames = {} },
			},
		},
		jediSettings = {
			autoImportModules = {},
			caseInsensitiveCompletion = true,
			debug = false,
		},
		markupKindPreferred = "markdown",
		workspace = {
			extraPaths = {},
			symbols = {
				ignoreFolders = { ".nox", ".tox", ".venv", "__pycache__", "venv" },
				maxSymbols = 20,
			},
		},
	},
})