ghcid
ghcid copied to clipboard
ghcid (fno-code) is twice as slow as `cabal repl` for my project
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
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?
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 )
...?
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
.
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.
- TemplateHaskell is enabled in all modules so we need object files in order to run TH splices.
- Object files get generated and put in a temporary directory, as no specific
-odir
is necessarily passed. They are not reused acrosscabal repl
calls. - 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.
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
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.