IHP 1.3 is out now!

Haskell Language Server performance

jpe90

Hello!

I got started with IHP recently and think it's fantastic so far. One issue I've had is related to the performance of the Haskell Language Server in an IHP project.

When it starts up, I've noticed it will peg a few cores of my CPU for a number of minutes, during which time the language server features are unavailable. This happens on both of my machines, one of which is a fairly powerful desktop, and doesn't occur when using the language server in non-IHP Haskell projects. I was wondering if this is a known issue and whether it's likely to improve in the future. Thank you!

Vlatko

Hi

The same issue occurs on my side and I haven't found any solution yet. Every time i start vim i need to wait for about 5 minutes for the language server to process the files.

It seems like it's something in the view files, the hsx code that causes the HLS to lock for a very long time. If i remove all these files, the problem doesn't occur.

Tested on two different linux distributions on an i7 CPU with 32GB RAM, on Vim, Sublime, VSCode.

Keep me posted if you find a solution, please. Thank you!

jpe90

Interesting find that it involves HSX, that explains why it's only IHP that gives trouble. I noticed that in both Sublime and VS code, the LSP process seems to output a message of progress being stuck at "21/33". I looked at neovim LSP debug logs (shown below) and saw that it gets stuck for a few minutes at that point, but I'm not really knowledgeable enough to see if anything weird is going on there.

I also saw that the version of the haskell language server bundled in IHP is 0.7.1, which looks like it's from December of 2020. Maybe it's better with newer versions? I'm new to Nix as well so I'm not sure how feasible it would be to try to rebuild IHP with a newer GHC and see if it would help, but I'll poke around.

LSP Debug log between progress of "21/23" and "22/23", with 2 minutes elapsed on a Ryzen 3700x:

[ DEBUG ] 2021-07-19T11:52:13-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:496 ]  "decoded"   {  jsonrpc = "2.0",  method = "$/progress",  params = {    token = "21",    value = {      kind = "report",      message = "21/33"    }  }}
[ DEBUG ] 2021-07-19T11:52:13-0400 ] /usr/share/nvim/runtime/lua/vim/lsp.lua:680 ]  "notification"  "$/progress"    {  token = "21",  value = {    kind = "report",    message = "21/33"  }}
[ DEBUG ] 2021-07-19T11:52:13-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/handlers.lua:445 ] "default_handler"   "$/progress"    {  client_id = 1,  params = {    token = "21",    value = {      kind = "report",      message = "21/33"    }  }}
[ DEBUG ] 2021-07-19T11:52:15-0400 ] /usr/share/nvim/runtime/lua/vim/lsp.lua:1035 ] "on_lines bufnr: 1, changedtick: 4, firstline: 3, lastline: 4, new_lastline: 4, old_byte_size: 24, old_utf32_size: 24, old_utf16_size: 24"  { "import GitHub (github') import qualified GitHub" }
[ DEBUG ] 2021-07-19T11:52:15-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:395 ]  "rpc.send.payload"  {  jsonrpc = "2.0",  method = "textDocument/didChange",  params = {    contentChanges = { {        range = {          end = {            character = 23,            line = 3          },          start = {            character = 23,            line = 3          }        },        rangeLength = 0,        text = " import qualified GitHub"      } },    textDocument = {      uri = "file:///home/solaire/development/haskell/test-ihp/Web/View/FavoriteRepos/New.hs",      version = 4    }  }}
[ DEBUG ] 2021-07-19T11:52:15-0400 ] /usr/share/nvim/runtime/lua/vim/lsp.lua:1035 ] "on_lines bufnr: 1, changedtick: 5, firstline: 4, lastline: 5, new_lastline: 4, old_byte_size: 24, old_utf32_size: 24, old_utf16_size: 24"  {}
[ DEBUG ] 2021-07-19T11:52:15-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:395 ]  "rpc.send.payload"  {  jsonrpc = "2.0",  method = "textDocument/didChange",  params = {    contentChanges = { {        range = {          end = {            character = 7,            line = 5          },          start = {            character = 7,            line = 4          }        },        rangeLength = 24,        text = ""      } },    textDocument = {      uri = "file:///home/solaire/development/haskell/test-ihp/Web/View/FavoriteRepos/New.hs",      version = 5    }  }}
[ DEBUG ] 2021-07-19T11:52:17-0400 ] /usr/share/nvim/runtime/lua/vim/lsp.lua:1035 ] "on_lines bufnr: 1, changedtick: 6, firstline: 3, lastline: 4, new_lastline: 5, old_byte_size: 48, old_utf32_size: 48, old_utf16_size: 48"  { "import GitHub (github')", "import qualified GitHub" }
[ DEBUG ] 2021-07-19T11:52:17-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:395 ]  "rpc.send.payload"  {  jsonrpc = "2.0",  method = "textDocument/didChange",  params = {    contentChanges = { {        range = {          end = {            character = 47,            line = 3          },          start = {            character = 23,            line = 3          }        },        rangeLength = 24,        text = "\nimport qualified GitHub"      } },    textDocument = {      uri = "file:///home/solaire/development/haskell/test-ihp/Web/View/FavoriteRepos/New.hs",      version = 6    }  }}
[ DEBUG ] 2021-07-19T11:52:19-0400 ] /usr/share/nvim/runtime/lua/vim/lsp.lua:895 ]  "LSP[hls]"  "client.request"    1   "textDocument/hover"    {  position = {    character = 7,    line = 4  },  textDocument = {    uri = "file:///home/solaire/development/haskell/test-ihp/Web/View/FavoriteRepos/New.hs"  }}  <function 1>    1
[ DEBUG ] 2021-07-19T11:52:19-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:395 ]  "rpc.send.payload"  {  id = 2,  jsonrpc = "2.0",  method = "textDocument/hover",  params = {    position = {      character = 7,      line = 4    },    textDocument = {      uri = "file:///home/solaire/development/haskell/test-ihp/Web/View/FavoriteRepos/New.hs"    }  }}
[ ERROR ] 2021-07-19T11:52:19-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ]  "rpc"   "haskell-language-server-wrapper"   "stderr"    "2021-07-19 11:52:19.73705201 [ThreadId 29] - Modified text document: file:///home/solaire/development/haskell/test-ihp/Web/View/FavoriteRepos/New.hs\n"
[ ERROR ] 2021-07-19T11:52:19-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ]  "rpc"   "haskell-language-server-wrapper"   "stderr"    "2021-07-19 11:52:19.73751297 [ThreadId 29] - Modified text document: file:///home/solaire/development/haskell/test-ihp/Web/View/FavoriteRepos/New.hs\n"
[ ERROR ] 2021-07-19T11:52:19-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ]  "rpc"   "haskell-language-server-wrapper"   "stderr"    "2021-07-19 11:52:19.7378414 [ThreadId 29] - Modified text document: file:///home/solaire/development/haskell/test-ihp/Web/View/FavoriteRepos/New.hs\n"
[ ERROR ] 2021-07-19T11:52:19-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ]  "rpc"   "haskell-language-server-wrapper"   "stderr"    "2021-07-19 11:52:19.73792255 [ThreadId 740] - GhcIde.hover entered (ideLogger)\n"
[ ERROR ] 2021-07-19T11:52:19-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ]  "rpc"   "haskell-language-server-wrapper"   "stderr"    "2021-07-19 11:52:19.73804319 [ThreadId 740] - Hover request at position 5:8 in file: /home/solaire/development/haskell/test-ihp/Web/View/FavoriteRepos/New.hs\n"
[ DEBUG ] 2021-07-19T11:52:21-0400 ] /usr/share/nvim/runtime/lua/vim/lsp.lua:895 ]  "LSP[hls]"  "client.request"    1   "textDocument/hover"    {  position = {    character = 17,    line = 4  },  textDocument = {    uri = "file:///home/solaire/development/haskell/test-ihp/Web/View/FavoriteRepos/New.hs"  }} <function 1>    1
[ DEBUG ] 2021-07-19T11:52:21-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:395 ]  "rpc.send.payload"  {  id = 3,  jsonrpc = "2.0",  method = "textDocument/hover",  params = {    position = {      character = 17,      line = 4    },    textDocument = {      uri = "file:///home/solaire/development/haskell/test-ihp/Web/View/FavoriteRepos/New.hs"    }  }}
[ ERROR ] 2021-07-19T11:52:21-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ]  "rpc"   "haskell-language-server-wrapper"   "stderr"    "2021-07-19 11:52:21.107823986 [ThreadId 920] - GhcIde.hover entered (ideLogger)\n"
[ ERROR ] 2021-07-19T11:52:21-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ]  "rpc"   "haskell-language-server-wrapper"   "stderr"    "2021-07-19 11:52:21.108020096 [ThreadId 920] - Hover request at position 5:18 in file: /home/solaire/development/haskell/test-ihp/Web/View/FavoriteRepos/New.hs\n"
[ START ] 2021-07-19T11:51:24-0400 ] LSP logging initiated
[ INFO ] 2021-07-19T11:52:25-0400 ] /usr/share/nvim/runtime/lua/vim/lsp.lua:1214 ]  "exit_handler"  {}
[ DEBUG ] 2021-07-19T11:54:25-0400 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:496 ]  "decoded"   {  jsonrpc = "2.0",  method = "$/progress",  params = {    token = "21",    value = {      kind = "report",      message = "22/33"    }  }}
Montmorency

There was an issue early on with IHP and HLS. The use of hsx template splices means the language server has to do a little bit of extra work on the back end and there could still be some issues with how that is working.

The easiest work around might be to disable some of the language server functionality for template splices and see if that stops things going in to overdrive. The IHP dev server/live compilation will still parse and type check all the hsx template splices so you won't lose any functionality.

marc PRO

I've just pushed an HLS update (0.7 -> 1.2) to IHP master. Can you update to the latest master and give it a try? Docs on updating to latest IHP master can be found here.

jpe90

Hey, I just updated to master and made sure HLS updated properly:

[nix-shell:~/development/haskell/test-ihp]$ haskell-language-server --version
haskell-language-server version: 1.2.0.0 (GHC: 8.10.4) (PATH: /nix/store/f18pwxhycvvnsim59bzrnspgzcbq82dw-haskell-language-server-1.2.0.0/bin/haskell-language-server)

But it still takes a few minutes to start up HLS in files w/ HSX, I didn't notice any speedup unfortunately. I haven't tried disabling splicing yet, wasn't quite sure how to do that but I'll figure it out when I get some spare time.

marc PRO

Then the issue is unrelated to our use of an old HLS version.

Could you open an issue at https://github.com/haskell/haskell-language-server/issues/new with the details you've mentioned here? :)

Zac Wood BUSINESS

I found a solution! The key is building HLS with dynamic linking. To do this you can change change your Config/nix/nixpkgs-config.nix file to the following:

# See https://ihp.digitallyinduced.com/Guide/package-management.html
{ ihp, additionalNixpkgsOptions, ... }:
let
  haskellLib = (import <nixpkgs> {}).haskell.lib;
in
  import "${toString ihp}/NixSupport/make-nixpkgs-from-options.nix" {
      ihp = ihp;
      haskellPackagesDir = ./haskell-packages/.;
      additionalNixpkgsOptions = additionalNixpkgsOptions;
      manualOverrides = self: super: {
        haskell-language-server = haskellLib.appendConfigureFlag
            super.haskell-language-server "--enable-executable-dynamic";
      };
  }