NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.08k stars 14.06k forks source link

Consider building GHC with Haskell libraries linked in statically #129245

Open nh2 opened 3 years ago

nh2 commented 3 years ago

GHC in nixpkgs is currently built with DYNAMIC_GHC_PROGRAMS=YES. This links Haskell libraries dynamically into GHC, and makes GHC's startup slow.

That in turn makes GHC a bit of a drag to use with nix, because even a simple --version call is unnecessarily slow (e.g. when used from scripts or in interactive feedback loops).

Here's a table of the startup time we're giving away:

startup time (s) --version time (s)
DYNAMIC_GHC_PROGRAMS=YES 0.30 0.12
DYNAMIC_GHC_PROGRAMS=NO 0.20 0.03
speedup factor 1.5x 4x

Finally, DYNAMIC_GHC_PROGRAMS=YES also makes the nix package larger: 435 MB vs 411 MB for static.

Click here to expand data:

``` # time /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/bin/ghc ghc: no input files Usage: For basic information, try the `--help' option. /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/bin/ghc 0.28s user 0.02s system 98% cpu 0.302 total ``` ``` # time /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/bin/ghc --version The Glorious Glasgow Haskell Compilation System, version 8.10.4 /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/bin/ghc --version 0.11s user 0.01s system 99% cpu 0.122 total ``` ``` # ldd /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/ghc linux-vdso.so.1 (0x00007fff371f5000) libHShaskeline-0.8.0.1-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../haskeline-0.8.0.1/libHShaskeline-0.8.0.1-ghc8.10.4.so (0x00007fe7bc68b000) libHSghc-8.10.4-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../ghc-8.10.4/libHSghc-8.10.4-ghc8.10.4.so (0x00007fe7b8e6c000) libHSterminfo-0.4.1.4-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../terminfo-0.4.1.4/libHSterminfo-0.4.1.4-ghc8.10.4.so (0x00007fe7b8e3d000) libHSprocess-1.6.9.0-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../process-1.6.9.0/libHSprocess-1.6.9.0-ghc8.10.4.so (0x00007fe7b8e00000) libHShpc-0.6.1.0-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../hpc-0.6.1.0/libHShpc-0.6.1.0-ghc8.10.4.so (0x00007fe7b8dca000) libHSghci-8.10.4-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../ghci-8.10.4/libHSghci-8.10.4-ghc8.10.4.so (0x00007fe7b8c3a000) libHSghc-heap-8.10.4-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../ghc-heap-8.10.4/libHSghc-heap-8.10.4-ghc8.10.4.so (0x00007fe7b8bd0000) libHSghc-boot-8.10.4-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../ghc-boot-8.10.4/libHSghc-boot-8.10.4-ghc8.10.4.so (0x00007fe7b8b2b000) libHSbinary-0.8.8.0-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../binary-0.8.8.0/libHSbinary-0.8.8.0-ghc8.10.4.so (0x00007fe7b8aa1000) libHSexceptions-0.10.4-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../exceptions-0.10.4/libHSexceptions-0.10.4-ghc8.10.4.so (0x00007fe7b8a69000) libHStemplate-haskell-2.16.0.0-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../template-haskell-2.16.0.0/libHStemplate-haskell-2.16.0.0-ghc8.10.4.so (0x00007fe7b885e000) libHSpretty-1.1.3.6-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../pretty-1.1.3.6/libHSpretty-1.1.3.6-ghc8.10.4.so (0x00007fe7b8800000) libHSghc-boot-th-8.10.4-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../ghc-boot-th-8.10.4/libHSghc-boot-th-8.10.4-ghc8.10.4.so (0x00007fe7b87d0000) libHSstm-2.5.0.0-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../stm-2.5.0.0/libHSstm-2.5.0.0-ghc8.10.4.so (0x00007fe7b87a9000) libHSmtl-2.2.2-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../mtl-2.2.2/libHSmtl-2.2.2-ghc8.10.4.so (0x00007fe7b8779000) libHStransformers-0.5.6.2-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../transformers-0.5.6.2/libHStransformers-0.5.6.2-ghc8.10.4.so (0x00007fe7b86a3000) libHSdirectory-1.3.6.0-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../directory-1.3.6.0/libHSdirectory-1.3.6.0-ghc8.10.4.so (0x00007fe7b8659000) libHSunix-2.7.2.2-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../unix-2.7.2.2/libHSunix-2.7.2.2-ghc8.10.4.so (0x00007fe7b8571000) libHStime-1.9.3-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../time-1.9.3/libHStime-1.9.3-ghc8.10.4.so (0x00007fe7b8487000) libHSfilepath-1.4.2.1-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../filepath-1.4.2.1/libHSfilepath-1.4.2.1-ghc8.10.4.so (0x00007fe7b8457000) libHScontainers-0.6.2.1-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../containers-0.6.2.1/libHScontainers-0.6.2.1-ghc8.10.4.so (0x00007fe7b815d000) libHSbytestring-0.10.12.0-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../bytestring-0.10.12.0/libHSbytestring-0.10.12.0-ghc8.10.4.so (0x00007fe7b803a000) libHSdeepseq-1.4.4.0-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../deepseq-1.4.4.0/libHSdeepseq-1.4.4.0-ghc8.10.4.so (0x00007fe7b801f000) libHSarray-0.5.4.0-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../array-0.5.4.0/libHSarray-0.5.4.0-ghc8.10.4.so (0x00007fe7b7f54000) libHSbase-4.14.1.0-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../base-4.14.1.0/libHSbase-4.14.1.0-ghc8.10.4.so (0x00007fe7b7634000) libHSinteger-gmp-1.0.3.0-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../integer-gmp-1.0.3.0/libHSinteger-gmp-1.0.3.0-ghc8.10.4.so (0x00007fe7b75f2000) libHSghc-prim-0.6.1-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../ghc-prim-0.6.1/libHSghc-prim-0.6.1-ghc8.10.4.so (0x00007fe7b7148000) libHSrts_thr-ghc8.10.4.so => /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/lib/ghc-8.10.4/bin/../rts/libHSrts_thr-ghc8.10.4.so (0x00007fe7b70b7000) libncursesw.so.6 => /nix/store/s5xpnmnhibl76a47wd65cwrwgjclzrnc-ncurses-6.2/lib/libncursesw.so.6 (0x00007fe7b7046000) libgmp.so.10 => /nix/store/157hv8qvfn8wgqjvrbkj69wa72b0if7n-gmp-6.2.1/lib/libgmp.so.10 (0x00007fe7b6fa4000) libc.so => /nix/store/dlvw7qab3m24m88f0iwc8zzal06ab92p-musl-1.2.2/lib/libc.so (0x00007fe7b6ef1000) libffi.so.7 => /nix/store/c1wiqgajygl66z3n1jl9m9baiykxwp1k-libffi-3.3/lib/libffi.so.7 (0x00007fe7b6ee4000) ``` ``` # time /nix/store/fh1wc8s9ja3vi9zxgazkp9rp48c4nx7d-ghc-8.10.4/bin/ghc ghc: no input files Usage: For basic information, try the `--help' option. /nix/store/fh1wc8s9ja3vi9zxgazkp9rp48c4nx7d-ghc-8.10.4/bin/ghc 0.18s user 0.01s system 95% cpu 0.204 total ``` ``` # time /nix/store/fh1wc8s9ja3vi9zxgazkp9rp48c4nx7d-ghc-8.10.4/bin/ghc --version The Glorious Glasgow Haskell Compilation System, version 8.10.4 /nix/store/fh1wc8s9ja3vi9zxgazkp9rp48c4nx7d-ghc-8.10.4/bin/ghc --version 0.02s user 0.01s system 89% cpu 0.034 total ``` ``` # ldd /nix/store/fh1wc8s9ja3vi9zxgazkp9rp48c4nx7d-ghc-8.10.4/lib/ghc-8.10.4/bin/ghc linux-vdso.so.1 (0x00007fffc5f99000) libncursesw.so.6 => /nix/store/s5xpnmnhibl76a47wd65cwrwgjclzrnc-ncurses-6.2/lib/libncursesw.so.6 (0x00007f50f4a13000) libgmp.so.10 => /nix/store/157hv8qvfn8wgqjvrbkj69wa72b0if7n-gmp-6.2.1/lib/libgmp.so.10 (0x00007f50f4973000) libc.so => /nix/store/dlvw7qab3m24m88f0iwc8zzal06ab92p-musl-1.2.2/lib/libc.so (0x00007f50f48c0000) libffi.so.7 => /nix/store/c1wiqgajygl66z3n1jl9m9baiykxwp1k-libffi-3.3/lib/libffi.so.7 (0x00007f50f48b3000) ``` ``` # du -sh /nix/store/fh1wc8s9ja3vi9zxgazkp9rp48c4nx7d-ghc-8.10.4/lib/ghc-8.10.4 411M /nix/store/fh1wc8s9ja3vi9zxgazkp9rp48c4nx7d-ghc-8.10.4/lib/ghc-8.10.4 # du -sh /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/ 435M /nix/store/ipdnx5ajcdplxvsff6lw55pdwsm8qpn6-ghc-8.10.4/ ```

In nixpkgs there is no benefit in linking Haskell libraries dynamically into programs. This is why the haskell-modules/generic-builder.nix defaults to enableSharedExecutables ? false for nix-built Haskell programs. We should do the same for GHC.

CC @NixOS/haskell @domenkozar


Edit: We should not do that for now, see https://github.com/NixOS/nixpkgs/issues/129245#issuecomment-874241200.

Instead, new closing criteria for this issue:

maralorn commented 3 years ago

Sounds good to me, thank you for figuring this out!

nh2 commented 3 years ago

I asked on #ghc chat and got suggestions that this is probably not a good idea:

@mpickering says:

There are a lot of issues with the linker built into GHC, so TH will not work with nixpkgs provided GHC for some cases. If you need to dynamically load certain libraries, just look at the HLS issue tracker.

@adamse concurs:

I agree with mpickering that it will cause pain for TH and sometimes ghci.


My original question was:

I'm planning to switch the nixpkgs GHC buidls from defaulting toDYNAMIC_GHC_PROGRAMS=YES to NO, to get 4x faster-starting GHCs. Will this prevent the creation of .so files entirely, thus making dynamic linking impossible, or will -dynamic-too still be active?

the latter part of which @adamse explained:

You can still build .so's (with or w/o -dynamic-too), but [concerns quoted above]


@mpickering explained that haskell-language-server distributes GHCs with Haskell libraries statically-linked in, and that this creates many problems for them. It is currently unclear to me why haskell-language-server does that then, as it seems that they could just as well provide a DYNAMIC_GHC_PROGRAMS=YES for download for e.g. VSCode users. I asked that upstream: https://github.com/haskell/haskell-language-server/issues/2000


I don't really understand why linking e.g. libHSfilepath-* statically into the ghc binary affects TemplateHaskell at all. If anybody could find a resource that we could link to from the GHC nix derivations, we could close this ticket as something we don't want to do.

nh2 commented 3 years ago

I don't really understand why linking e.g. libHSfilepath-* statically into the ghc binary affects TemplateHaskell at all. If anybody could find a resource that we could link to from the GHC nix derivations, we could close this ticket as something we don't want to do.

@mpickering / @adamse / @bgamari If you have time, could you help us out with a good explanation or upstream GHC ticket to link to?

adamse commented 3 years ago

I think the main issue is linking the RTS statically, this currently causes GHCi and TemplateHaskell to use the home grown runtime linker to load other haskell packages object code. I don't quite remember all the details here though.

I think that on some targets it would be possible to use dlopen instead of the ghc rts linker even with a statically linked rts (with ld's --dynamic-list for rts symbols), but this requires work on GHC and I understand that not all targets have a functioning dl library (musl?).

stale[bot] commented 2 years ago

I marked this as stale due to inactivity. → More info

NorfairKing commented 5 months ago

Definitely not stale.