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

Significant slowdown when open a Julia with in single file mode #423

Open
2 tasks done
ronisbr opened this issue Jun 5, 2024 · 1 comment
Open
2 tasks done

Significant slowdown when open a Julia with in single file mode #423

ronisbr opened this issue Jun 5, 2024 · 1 comment

Comments

@ronisbr
Copy link

ronisbr commented Jun 5, 2024

Problem description

When we open a Julia file using the LSP installed by Mason and configured by maons-lspconfig, we see a huge slowdown when opening in single file mode. This slowdown does not happen if you open the file inside a Julia project, for example, or if you set the configuration env_path.

Why do you think this is an issue with mason-lspconfig.nvim?

mason-lspconfig provides a clever way to select which environment Julia LSP will use:

  1. Use julia_env_path if it is defined.
  2. Search for a Julia project folder.
  3. Call Julia to obtain the default environment.

However, step 3 causes a huge Neovim slowdown (UI lock) because it must wait Julia to startup, evaluate the default environment, and exit (

).

This approach is robust because it will work most of the time with the default configuration. The problem happens when you work with a lot stand alone files. In this case, if you do not setup julia_env_path, you have almost 2 s of delay every time you open a Julia file.

Here is the time it takes for Julia to retrieve the env path in my machine (M1 Ultra):

$ time julia --startup-file=no --history-file=no -e "using Pkg; print(dirname(Pkg.Types.Context().env.project_file))"
/Users/Ronan/.julia/environments/v1.10julia --startup-file=no --history-file=no -e   1.62s user 0.92s system 504% cpu 0.504 total

Setting julia_env_path is not a global solution here, because most of time you are working in a project, you want to use the environment of that project and julia_env_path overrides everything.

There are some solutions (when we decided which one is best I submit a PR):

  1. Change the logic to always try to find a Julia project folder before considering julia_env_path (bad, it will break some setups).
  2. Add a new variable (default_julia_env_path or something) which shall be used instead querying Julia for the default environment path (adds a new variable and can be a little confusing).
  3. Make that pcall asynchronous somehow (I do not know if it is possible).
  4. Suggestions ?

Neovim version (>= 0.7)

NVIM v0.10.0
Build type: Release
LuaJIT 2.1.1716656478
Run "nvim -V1 -v" for more info

Operating system/version

macOS 14.5

I've manually reviewed the Nvim LPS client log (:LspLog) to find potential errors

  • Yes

I've recently downloaded the latest plugin version of mason.nvim, mason-lspconfig.nvim, and nvim-lspconfig

  • Yes

Affected language servers

julials

Steps to reproduce

  1. Configure julials with default values without setting env_path.
  2. Start neovim and opens a Julia file in a folder that is neither a git or Julia project repositories.
  3. Configure env_path.
  4. Start neovim and opens the same Julia file in step 2.

Actual behavior

Neovim UI locks in step 2 but the lock is gone in step 4.

Expected behavior

Neovim UI should not lock or, at least, we need a new way to avoid locking.

LspInfo

N/A, the issue was identified in the source code.

LspLog

N/A, the issue was identified in the source code.

Healthcheck

N/A, the issue was identified in the source code.

Screenshots or recordings

No response

@ronisbr
Copy link
Author

ronisbr commented Jun 5, 2024

For anyone with this problem, the temporary solution is to add this configuration to julials:

  julials = {
    julia_env_path = "~/.julia/environments/v1.10/",

    on_new_config = function(config, workspace_dir)
      local _    = require("mason-core.functional")
      local fs   = require("mason-core.fs")
      local path = require("mason-core.path")

      -- The default configuration used by `mason-lspconfig`:
      --
      --   https://github.com/williamboman/mason-lspconfig.nvim/blob/main/lua/mason-lspconfig/server_configurations/julials/init.lua
      --
      -- has the following logic to obtain the current environment path:
      --
      --   1. Check if `env_path` is defined.
      --   2. Check if we are in a Julia project.
      --   3. Call julia to return the current env path.
      --
      -- However, the third step causes a significant slow down when Julia is called in a
      -- single file mode because it must wait loading Julia. Here, we will invert the
      -- logic:
      --
      --   1. Check if we are in a Julia project.
      --   2. Check if `env_path` is defined.
      --   3. Call julia to return the current env path.
      --
      -- Hence, if we define `env_path`, we can still use the project folder as root and
      -- avoid the slowdown in the single file case.
      local env_path = nil
      local file_exists = _.compose(fs.sync.file_exists, path.concat, _.concat { workspace_dir })
      if (file_exists { "Project.toml" } and file_exists { "Manifest.toml" }) or
        (file_exists { "JuliaProject.toml" } and file_exists { "JuliaManifest.toml" }) then
        env_path = workspace_dir
      end

      if not env_path then
        env_path = config.julia_env_path and vim.fn.expand(config.julia_env_path)
      end

      if not env_path then
        local ok, env = pcall(vim.fn.system, {
          "julia",
          "--startup-file=no",
          "--history-file=no",
          "-e",
          "using Pkg; print(dirname(Pkg.Types.Context().env.project_file))",
        })
        if ok then
          env_path = env
        end
      end

      config.cmd = {
        vim.fn.exepath "julia-lsp",
        env_path,
      }
      config.cmd_env = vim.tbl_extend("keep", config.cmd_env or {}, {
        SYMBOL_SERVER = config.symbol_server,
        SYMBOL_CACHE_DOWNLOAD = (config.symbol_cache_download == false) and "0" or "1",
      })
    end,
  },

ronisbr added a commit to ronisbr/nvim that referenced this issue Jun 5, 2024
This workaround is required due to the issue described in:

williamboman/mason-lspconfig.nvim#423
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant