hie-nix icon indicating copy to clipboard operation
hie-nix copied to clipboard

hie executables should be dynamically linked

Open mpickering opened this issue 5 years ago • 11 comments

Until very recently nix built haskell packages with --enable-library-for-ghci and --enable-split-sections which causes terrible performance in the runtime linker that ghci uses when compiled in the static manner.

https://github.com/NixOS/nixpkgs/pull/59297

The workaround is to dynamically link the executable and then the system dynamic linker is used instead of the one built into GHC. The difference between the two is significant (2 mins vs 0.3s).

https://gitlab.haskell.org/ghc/ghc/issues/15524

It would seem prudent to build the hie in this manner in hie-nix as users might also run into this problem using an older nixpkgs commit.

mpickering avatar Apr 13 '19 16:04 mpickering

Thanks for the report!

Linking hie-nix dynamically takes a lot of space (there are 3 GHCs with 200 packages in the closure). I will bump nixpkgs (as far as I understand the fix in nixpkgs addresses the issue for static linking) and advise everyone to upgrade.

domenkozar avatar Apr 15 '19 04:04 domenkozar

Bumping the nixpkgs which you use to build HIE won't fix the issue. It is the tooling users who need to bump the version of nixpkgs they use.

mpickering avatar Apr 15 '19 07:04 mpickering

So only those that use hie with Nix built projects would be affected?

domenkozar avatar Apr 15 '19 08:04 domenkozar

The runtime linker built into GHC performs worse than the system linker. When you statically link the executable then GHC API programs use the built-in rather than system linker.

There are some things you can do to make the runtime linker perform very badly.

  1. Enabling --split-sections
  2. Enabling --build-library-for-ghci

Enabling both of these together causes some non-linear behavior to be exhibited which means loading packages such as jsaddle-dom take a very very long time.

So in theory anyone can be affected but because the only packaging I know of which enabled these two options together was nixpkgs then it is realistically only people who use nix to manage haskell dependencies who are affected.

mpickering avatar Apr 15 '19 10:04 mpickering

AFAIK split sections are enabled by default on Linux at least, so it's really about (2).

I'm not sure if 100% of hie-nix users should suffer to download a huge closure or a few % of hie-nix users that use Nix should be notified somehow to upgrade.

domenkozar avatar Apr 15 '19 12:04 domenkozar

Surely every person who uses hie-nix uses nix?

mpickering avatar Apr 15 '19 12:04 mpickering

I don't, but I see your point. Let me see how big is the closure with dynamic linking.

domenkozar avatar Apr 16 '19 10:04 domenkozar

Closure size goes from 6.6GB to 13GB.

domenkozar avatar Apr 17 '19 03:04 domenkozar

Hey I just made https://github.com/infinisil/all-hies which includes builds for all GHC versions. @domenkozar notified me regarding this issue, but I'm still a bit confused.

Do I understand it right that:

  • Statically built Haskell executables (like hie-nix or all-hies) have very bad runtime performance (you mentioned for linking, but HIE afaik doens't do any linking?)
  • This can be fixed by the end user upgrading their nixpkgs version used for their haskell projects (but what has this to do with HIE?)
  • or this can be fixed by dynamically linking HIE (but what has this to do with he users project?)

I'd really like some concrete answers to that.

infinisil avatar Apr 27 '19 08:04 infinisil

  1. Statically linked executables which use the GHC API have poor performance when loading .so files which is required when TemplateHaskell is enabled. The problem is much worse if you turn on --split-sections and even worse when you turn on --enable-library-for-ghci.

see: https://gitlab.haskell.org/ghc/ghc/issues/15524

  1. If a user upgrades their nixpkgs then nix will only enable --split-sections and not --enable-library-for-ghci so the load times will be much faster but still slower than dynamic linking.
  2. The only workaround to mitigate the packaging decision by nix is to dynamically link the hie executable.

mpickering avatar Apr 27 '19 12:04 mpickering

Ahh! Thanks a lot, that cleared everything up, especially the Haskell API part. I actually had problems with loading times of TH projects when I started using HIE (5 minutes to start..), so I avoided TH until now. If dynamic linking solves this problem then that's a very good motivator to start using it.

infinisil avatar Apr 27 '19 13:04 infinisil