ghcid icon indicating copy to clipboard operation
ghcid copied to clipboard

ghcid (fno-code) is twice as slow as `cabal repl` for my project

Open jberryman opened this issue 4 years ago • 6 comments

I'm observing this with ghc 9.1 and cabal-install 3.4 and can't easily test on 8.10.2 at the moment, but the repro for 8.10.2 would look like:

  • clone https://github.com/hasura/graphql-engine
  • cd server && ln -s cabal.project.dev-sh.local cabal.project.local
  • cabal repl (takes about 60 sec)
  • ghcid (takes something like twice that)

It looks like it's the same behavior with just cabal repl --repl-options="-fno-code"

ghcid is also slower overall after initial startup, when a file changes

Maybe this is an upstream issue, but seemed better to open it here

jberryman avatar Jan 29 '21 17:01 jberryman

When you start the project, what does it print out as the command line it uses to compile things? If you do -fno-code to cabal, are you saying its the "same behaviour" as in also slow, or also fast? If you do ghcid -c "cabal repl" does Ghcid return to the same speed or faster than Cabal repl?

ndmitchell avatar Jan 31 '21 20:01 ndmitchell

When you start the project, what does it print out as the command line it uses to compile things?

Loading cabal repl --repl-options=-fno-code --repl-options=-fno-break-on-exception --repl-options=-fno-break-on-error --repl-options=-v1 --repl-options=-ferror-spans --repl-options=-j ...
Build profile: -w ghc-9.1.20201218 -O1
In order, the following will be built (use -v for more details):
 - graphql-engine-1.0.0 (lib) (ephemeral targets)
Preprocessing library for graphql-engine-1.0.0..
GHCi, version 9.1.20201218: https://www.haskell.org/ghc/  :? for help
[  1 of 191] Compiling Control.Arrow.Trans ( src-lib/Control/Arrow/Trans.hs, /tmp/ghc10460_0/ghc_28.o )
[  2 of 191] Compiling Control.Arrow.Extended ( src-lib/Control/Arrow/Extended.hs, /tmp/ghc10460_0/ghc_26.o )
[  3 of 191] Compiling Control.Lens.Extended ( src-lib/Control/Lens/Extended.hs, /tmp/ghc10460_0/ghc_32.o )
.... SNIP .....

If you do -fno-code to cabal, are you saying its the "same behaviour" as in also slow, or also fast?

Sorry! I mean cabal repl -fno-code is just as slow as ghcid, while just cabal repl is fast.

If you do ghcid -c "cabal repl" does Ghcid return to the same speed or faster than Cabal repl?

Yes.

In retrospect, I'm not sure why I opened this in ghcid, sorry... (I guess it seemed like the right place since it's more user-facing), but feel free to close. I'll comment here if I can open a ghc ticket with a small repro.

Is it expected that the -fno-code would show:

[  1 of 191] Compiling Control.Arrow.Trans ( src-lib/Control/Arrow/Trans.hs, /tmp/ghc10460_0/ghc_28.o )

vs, without the flag:

[  1 of 191] Compiling Control.Arrow.Trans ( src-lib/Control/Arrow/Trans.hs, interpreted )

...?

jberryman avatar Jan 31 '21 22:01 jberryman

It seems as though -fno-code on your project is causing it to compile to object files. Maybe that's something to do with template Haskell? Or just a flag out bug? Definitely one for GHC - although if it's deliberate and widespread I might change the default to not pass -fno-code.

ndmitchell avatar Jan 31 '21 22:01 ndmitchell

I can reproduce this but not as bad as @jberryman reports. I think it is due to how generating object files is slower than generating bytecode.

The situation is not very optimal here.

  1. TemplateHaskell is enabled in all modules so we need object files in order to run TH splices.
  2. Object files get generated and put in a temporary directory, as no specific -odir is necessarily passed. They are not reused across cabal repl calls.
  3. If you instead pass -fobject-code, initial load is slower, but reloads much faster, as object files are reused.

So I think it's a GHC bug that -fno-code can be worse than -fobject-code in some situations.

mpickering avatar Mar 24 '21 09:03 mpickering

Perhaps ghcide should also pass -fwrite-interface, that would make subsequent calls to ghcide potentially faster.

https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/phases.html?highlight=write%20interface#ghc-flag--fwrite-interface

mpickering avatar Mar 24 '21 09:03 mpickering

One concern with -fwrite-interface is that the interface files might not go where people expect them. If ghcid has run ghci directly, they probably by default appear next to the source code. If it's via stack/cabal, the interface files might not be compatible with what stack/cabal want as they probably pass different flags. As such, anything that causes ghcid to write to disk by default seems undesirable...

But I'm not the expert here - poking ghci to get the behaviour we want is getting increasingly difficult.

ndmitchell avatar Apr 05 '21 15:04 ndmitchell