Opened 4 years ago

Last modified 3 months ago

#3658 new task

Dynamically link GHCi (and use system linker) on platforms that support it

Reported by: simonmar Owned by: thoughtpolice
Priority: high Milestone: 7.8.3
Component: GHCi Version: 6.10.4
Keywords: dynamic link Cc: morrow@…, howard_b_golden@…, pho@…, dterei, bos@…, george.colpitts@…, hvr, andreas.voellmy@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty: Unknown
Test Case: Blocked By: #5987
Blocking: #781, #1883, #3242, #3372, #3654, #4244, #5062, #5197, #6107, #7056, #7072, #7097, #7103, #7316, #7329, #7389, #7475, #7687 Related Tickets:

Description (last modified by ezyang)

In 6.14.1 we should switch to shipping a dynamically linked GHCi binary, on those platforms for which dynamic linking is supported (currently Linux; MacOS X and Windows support is in progress).

Advantages

  • The GHCi binary is smaller
  • some packages don't need to be loaded on startup: lower memory use
  • GHCi startup might be quicker (or it might not)
  • some hacks due to having two copies of the base package are not necessary (see rts/Globals.c)
  • We might save some space in the distributions.
  • It takes us a step closer to not needing the RTS linker at all
  • It takes us a step closer to using dynamic linking by default, which is where we want to go ultimately

Potential Issues

  • Do we run into any problems with GHCi and the user program sharing the same stdin/stdout/stderr handles? Do we need to virtualise these explicitly in the GHCi front end?
  • We cannot revert CAFs in packages that are shared by GHC and the user program. There are some old non-working hacks related to reverting CAFs when GHCi is dynamically linked (see KeepCAFsForGHCi) that need to be cleaned out. CAFs can only be reverted in code loaded by the RTS linker. We need to think about whether this is a necessary feature or not: we have never supported CAF reverting for interpreted code anyway. One reason to have it was so that you can recover after saying getContents at the GHCi prompt, but we can provide other ways to work around that. However, if we eliminated HEAP_ALLOCED (#8199), as a side effect of this implementation, this might be doable, as we no longer have to reach our fingers into the data section of dynamically linked in libraries to revert a CAF; all of the CAFs are copied to dynamic memory space first. (The current implementation doesn't work for that, however!)
  • There will be installation/binary-dist issues to resolve; currently we don't install any dynamically-linked binaries.

Open questions

  • Whether we continue to use the same binary for GHC and GHCi is an open question: it would be possible to provide a separate statically-linked GHC binary if performance of the dynamically-linked version was an issue.
  • We might as well dynamically-link Haddock, and the other tools that come with GHC too.

Change History (48)

comment:1 Changed 4 years ago by morrow

  • Cc morrow@… added
  • Type of failure set to None/Unknown

comment:2 Changed 4 years ago by hgolden

  • Cc howard_b_golden@… added

comment:3 Changed 4 years ago by PHO

  • Cc pho@… added

comment:4 Changed 4 years ago by simonmar

Some progress towards this:

Wed Apr 28 21:52:41 BST 2010  Simon Marlow <marlowsd@gmail.com>
  * Add $(GhcDynamic) knob, set to YES to get stage2 linked with -dynamic
  Default currently NO.
  
  Validate passed with GhcDynamic=YES on x86/Linux here.
  
  The compiler is currently slower on x86 when linked -dynamic,
  because the GC inner loop has been adversely affected by -fPIC, I'm
  looking into how to fix it.

The compiler really is slower when linked dynamically, at least on x86, because of the overhead of -fPIC - the GC is significantly slower. I looked into it but didn't find a way to fix it. We might have to ship separate GHC and GHCi binaries on x86; I expect this to be better on x86_64, but haven't measured it yet.

Currently, Cabal doesn't build packages dynamically by default, and this will become an accute issue when GHCi is linked dynamically. We need to do the package system changes needed to register each way separately, so that 'cabal install --enable-dynamic' works properly. Either that or Cabal has to enable dynamic by default.

GHCi is quicker to start up when dynamically linked: 0.1s vs. 0.23s.

comment:5 Changed 4 years ago by simonpj

  • Milestone changed from 7.0.1 to 7.2.1

Bumping this to 7.2. We just aren't going to get this done for 7.0.

comment:6 Changed 4 years ago by simonmar

  • Blocking 781 added

(In #781) To fix this we need to use -fPIC by default on x86_64, which is also what we need for #3658. So let's plan to do this in 7.2, when we've thought through the implications of moving to dynamic linking by default.

comment:7 Changed 4 years ago by simonmar

This has just become more important since we ran into an arbitrary limit in the OS X object file format: http://www.haskell.org/pipermail/cvs-ghc/2010-September/055908.html.

Here's a rough plan of action:

  • measure the performance impact of dynamic linking. If the impact is too much, fixing that is a blocking issue. We can't ship a separate static GHC binary, because GHC needs to use TH, so GHC itself has to be dynamic.
  • make a build system switch to enable dynamic-by-default
  • make GHC report whether it is a dynamic-default compiler, in the --info output.
  • modify Cabal to use --enable-*-dynamic and --disable-library-vanilla, if GHC is dynamic.
  • implement loading of object files by first calling 'gcc -shared' (or equiv. ld command line), and then dlopen(). Measure the performance impact of that. Figure out whether we need to cache the results of gcc -shared or regenerate them into $TMPDIR each time.
  • enable dynamic-by-default for some platforms.
  • Later: we need to track ways properly in Cabal and the package database.

comment:8 Changed 4 years ago by simonmar

Furthermore:

  • If the user mentions a .c file on the command line, we have to compile that with -fPIC too. The same goes for our _stub files.

comment:9 Changed 3 years ago by dterei

  • Cc dterei added

comment:10 Changed 3 years ago by igloo

  • Milestone changed from 7.4.1 to 7.6.1

Punting.

comment:11 Changed 20 months ago by igloo

I think this is where we are:

  • Dynamically linking GHC is relatively easy (compared to dynamically linking executables in general). GHC already ships with the actual dynamic libraries, so we can use assemblies on Windows, $ORIGIN on ELF and @loader_path on OS X to find the dynlibs with a relative path.
  • To load .o files in the working directory compiled by the user, ghci can link them into a DLL in /tmp and then dlopen that DLL
  • Problem 1: The .o files in the working directory would need to be built the dyn way
  • Problem 2: #5987: There are currently too many symbols to make a ghc DLL on Windows

One solution (easy to implement, but not very user-friendly) to problem 1 would be to require that users use -dynamic when compiling things they want ghci to be able to use.

Perhaps another would be for ghc to make both .o and .dyn_o by default. I think the two ways are identical apart from the final codegen phase.

comment:12 Changed 20 months ago by igloo

  • Blocking 7207 added

comment:13 Changed 20 months ago by igloo

  • Blocked By 5987 added
  • Blocking 1883, 2283, 3242, 7097, 7134 added

comment:14 Changed 20 months ago by igloo

  • Milestone changed from 7.6.1 to 7.8.1

comment:15 Changed 20 months ago by simonmar

Problem 3 is that Cabal doesn't track ways properly yet, although hopefully the Commentary/GSoCMultipleInstances project will address that.

I quite like the idea of building .o and .dyn_o at the same time, and sharing the .hi file between the two. That would at least reduce the pain of having to build things twice. This could then be the default mode of compilation in Cabal.

I still think the right way to fix this is to enable -dynamic by default on Unix systems (pending some performance measurements), after we have fixed Cabal to track ways. On Windows, Ian's idea of building with -dynamic but linking statically sounds interesting.

comment:16 Changed 20 months ago by igloo

  • Blocking 5435 added

comment:17 Changed 19 months ago by igloo

  • Blocking 3372, 3654, 4244, 5062, 5197, 6107 added
  • Owner set to igloo
  • Summary changed from Dynamically link GHCi on platforms that support it to Dynamically link GHCi (and use system linker) on platforms that support it

comment:18 Changed 18 months ago by igloo

  • Blocking 7072 added

comment:19 Changed 18 months ago by igloo

  • Blocking 7357 added

(In #7357) I can't reproduce this for some reason.

Nevertheless, it would be fixed by #3658.

comment:20 Changed 17 months ago by igloo

  • Blocking 7299 added

(In #7299) I can reproduce this.

However, it doesn't happen with a dynamic-by-default build.

comment:21 Changed 17 months ago by igloo

  • Blocking 7056 added

(In #7056) This would be fixed by dynamic-by-default.

comment:22 Changed 17 months ago by igloo

  • Blocking 7103 added

(In #7103) This would be fixed by dynamic-by-default.

comment:23 Changed 17 months ago by igloo

  • Blocking 7043 added

(In #7043) This doesn't happen if dynamic-by-default is enabled.

comment:24 Changed 16 months ago by igloo

  • Blocking 7475 added

(In #7475) Thanks for the report. This looks like it's probably a duplicate of #7043, although that ticket claims to only affect 32bit platforms.

comment:25 Changed 15 months ago by bos

  • Blocking 7357 removed

comment:26 Changed 15 months ago by bos

  • Cc bos@… added

comment:27 Changed 15 months ago by bos

  • Blocking 7207 removed

comment:28 Changed 15 months ago by igloo

  • Blocking 7299 removed

comment:29 Changed 13 months ago by igloo

  • Blocking 3333 added

comment:30 Changed 13 months ago by igloo

  • Blocking 7329 added

comment:31 Changed 13 months ago by igloo

  • Blocking 7389 added

(In #7389) Thanks for the report.

I'm a little confused about why the ghc linker is being used in this case, but the error comes from it, so it must be.

In any case, this therefore ought to be fixed by #3658.

comment:32 Changed 13 months ago by igloo

  • Blocking 7687 added

(In #7687) Thanks for the report. This will be fixed by using the system linker in ghci.

comment:33 Changed 12 months ago by igloo

  • Blocking 4244 removed

comment:34 Changed 12 months ago by igloo

  • Blocking 4244 added

comment:35 Changed 12 months ago by igloo

  • Blocking 7316 added

(In #7316) This should be fixed by using dynamic libraries to implement GHCi.

comment:36 Changed 12 months ago by igloo

  • Blocking 7889 added

(In #7889) Thanks for the report. I'm hoping to fix this by fixing #3658.

comment:37 Changed 9 months ago by igloo

Current plan/status is in DynamicGhcPrograms.

comment:38 Changed 9 months ago by igloo

  • Owner igloo deleted

comment:39 Changed 9 months ago by george.colpitts

  • Cc george.colpitts@… added
  • Keywords dynamic link added

comment:40 Changed 8 months ago by thoughtpolice

  • Blocking 7889 removed

comment:41 Changed 8 months ago by ezyang

  • Description modified (diff)

If we eliminated HEAP_ALLOCED (#8199), as a side effect of this implementation, this might be doable, as we no longer have to reach our fingers into the
data section of dynamically linked in libraries to revert a CAF; all of the CAFs
are copied to dynamic memory space first. (The current implementation doesn't
work for that, however!)

comment:42 Changed 7 months ago by ezyang

  • Blocking 5435 removed

comment:43 Changed 7 months ago by bgamari

  • Blocking 7043 removed

comment:44 Changed 7 months ago by thoughtpolice

  • Cc hvr added
  • Owner set to thoughtpolice

comment:45 Changed 7 months ago by AndreasVoellmy

  • Cc andreas.voellmy@… added

comment:46 Changed 6 months ago by thoughtpolice

  • Blocking 3333 removed

comment:47 Changed 3 months ago by thoughtpolice

  • Blocking 7134 removed

comment:48 Changed 3 months ago by thoughtpolice

  • Blocking 2283 removed
Note: See TracTickets for help on using tickets.