hie-nix
hie-nix copied to clipboard
hie executables should be dynamically linked
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.
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.
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.
So only those that use hie with Nix built projects would be affected?
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.
- Enabling
--split-sections
- 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.
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.
Surely every person who uses hie-nix uses nix?
I don't, but I see your point. Let me see how big is the closure with dynamic linking.
Closure size goes from 6.6GB to 13GB.
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.
- Statically linked executables which use the GHC API have poor performance when loading
.so
files which is required whenTemplateHaskell
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
- 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. - The only workaround to mitigate the packaging decision by nix is to dynamically link the
hie
executable.
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.