Haddock spends a lot of time building code if TemplateHaskell is enabled
Summary
I'm looking at Haddock's performance, and noticed that the time for building Haddock in persistent-test
is absolutely dominated by doing code generation.
I've attached a profiteur
HTML in a gist in this upstream Haddock issue: https://github.com/haskell/haddock/issues/1547 Happy to add a .prof
if that's easier.
This happens when TemplateHaskell
or QuasiQuotes
is enabled, even if TemplateHaskell
is not actually used. If I disable the extensions, then much less code is generated.
Here's the log output with TemplateHaskell
on:
[41 of 41] Compiling UpsertTest ( src/UpsertTest.hs, /tmp/ghc927461_0/ghc_86.o )
*** Parser [UpsertTest]:
!!! Parser [UpsertTest]: finished in 1.48 milliseconds, allocated 4.784 megabytes
*** Renamer/typechecker [UpsertTest]:
*** processModule:
*** createInterface:
!!! createInterface: finished in 0.40 milliseconds, allocated 2.046 megabytes
!!! processModule: finished in 0.66 milliseconds, allocated 2.371 megabytes
!!! Renamer/typechecker [UpsertTest]: finished in 17.32 milliseconds, allocated 32.451 megabytes
*** Desugar [UpsertTest]:
Result size of Desugar (before optimization)
= {terms: 4,246, types: 4,980, coercions: 882, joins: 0/672}
Result size of Desugar (after optimization)
= {terms: 2,890, types: 3,218, coercions: 701, joins: 0/160}
!!! Desugar [UpsertTest]: finished in 5.89 milliseconds, allocated 11.031 megabytes
*** Simplifier [UpsertTest]:
Result size of Simplifier iteration=1
= {terms: 3,069, types: 3,432, coercions: 1,027, joins: 0/166}
Result size of Simplifier
= {terms: 3,048, types: 3,412, coercions: 1,023, joins: 0/165}
!!! Simplifier [UpsertTest]: finished in 9.64 milliseconds, allocated 17.176 megabytes
*** CoreTidy [UpsertTest]:
!!! CoreTidy [UpsertTest]: finished in 0.75 milliseconds, allocated 2.167 megabytes
Result size of Tidy Core
= {terms: 3,048, types: 3,412, coercions: 1,023, joins: 0/165}
*** CorePrep [UpsertTest]:
Result size of CorePrep
= {terms: 5,098, types: 5,952, coercions: 1,023, joins: 0/1,144}
!!! CorePrep [UpsertTest]: finished in 4.04 milliseconds, allocated 6.778 megabytes
*** CoreToStg [UpsertTest]:
*** Stg2Stg:
!!! CoreToStg [UpsertTest]: finished in 2.15 milliseconds, allocated 5.676 megabytes
*** CodeGen [UpsertTest]:
!!! CodeGen [UpsertTest]: finished in 228.48 milliseconds, allocated 258.712 megabytes
*** WriteIface [/tmp/ghc927461_0/ghc_85.hi]:
!!! WriteIface [/tmp/ghc927461_0/ghc_85.hi]: finished in 0.22 milliseconds, allocated 1.194 megabytes
With TemplateHaskell
disabled,
[41 of 41] Compiling UpsertTest ( src/UpsertTest.hs, nothing )
*** Parser [UpsertTest]:
!!! Parser [UpsertTest]: finished in 1.95 milliseconds, allocated 4.994 megabytes
*** Renamer/typechecker [UpsertTest]:
*** processModule:
*** createInterface:
!!! createInterface: finished in 1.39 milliseconds, allocated 2.073 megabytes
!!! processModule: finished in 1.66 milliseconds, allocated 2.398 megabytes
!!! Renamer/typechecker [UpsertTest]: finished in 17.57 milliseconds, allocated 33.295 megabytes
*** Desugar [UpsertTest]:
Result size of Desugar (before optimization)
= {terms: 4,246, types: 4,980, coercions: 882, joins: 0/672}
Result size of Desugar (after optimization)
= {terms: 2,890, types: 3,218, coercions: 701, joins: 0/160}
!!! Desugar [UpsertTest]: finished in 5.93 milliseconds, allocated 10.748 megabytes
*** CoreTidy [UpsertTest]:
!!! CoreTidy [UpsertTest]: finished in 0.13 milliseconds, allocated 0.033 megabytes
One easy win here is only doing code gen if the module actually uses TemplateHaskell
- I feel like GHC has a way of knowing this ahead-of-time, since the old recompilation-avoidance logic would skip recompiling a module with TemplateHaskell
enabled unless the module actually used TemplateHaskell
.
Steps to reproduce
Either build haddock
with profiling and use that to build docs, or, for a much easier time, do:
git clone git@github.com:yesodweb/persistent
cd persistent
cabal haddock --haddock-options="--optgc=\"-v2\""
and look at the output for CodeGen
printing.
Expected behavior
Ideally, not do code generation unless the module really requires it, and not just assume that it does.
Environment
- GHC version used: 9.4.3, 9.4.2
Optional:
- Operating System:
- System Architecture: