[GHC] #11375: Type aliases twice as slow to compile as closed type families.
GHC
ghc-devs at haskell.org
Thu Jan 7 21:59:36 UTC 2016
#11375: Type aliases twice as slow to compile as closed type families.
-------------------------------------+-------------------------------------
Reporter: danilo2 | Owner:
Type: bug | Status: new
Priority: high | Milestone:
Component: Compiler (Type | Version: 8.1
checker) |
Resolution: | Keywords:
Operating System: MacOS X | Architecture: aarch64
Type of failure: Compile-time | Test Case:
performance bug |
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Description changed by danilo2:
Old description:
> Hello guys! This bug is awkard at last to me. So I notiiced today, that
> using type aliases in my code takes twice as long to copile than using
> closed type families with just single member. So to be most precise -
> when I replace the following line:
> {{{
> type XQ1 m a = Targets (Match m a)
> }}}
>
> with
>
> {{{
> type family XQ1 m a where XQ1 m a = Targets (Match m a)
> }}}
>
> the compilation time drops from 15s to 7s (this type alias is heavily
> used across the application). I think it could be somehow related to the
> famous #8095 bug, but I can of course be wrong here.
>
> Unfortunetally the codebase is pretty big and its not so easy to make a
> minimal example, but I'll try to work on it during the upcoming weekend
> (please notify me if that would not be necessary).
>
> And some statistics from `-dshow-passes`:
>
> When using type alias:
> {{{
> *** Parser:
> *** Renamer/typechecker:
> *** Desugar:
> Result size of Desugar (after optimization)
> = {terms: 10,303, types: 66,949, coercions: 16,383,834}
> *** Simplifier:
> Result size of Simplifier iteration=1
> = {terms: 10,722, types: 75,391, coercions: 16,507,338}
> Result size of Simplifier iteration=2
> = {terms: 10,550, types: 74,437, coercions: 16,504,770}
> Result size of Simplifier iteration=3
> = {terms: 10,543, types: 74,347, coercions: 16,504,734}
> Result size of Simplifier
> = {terms: 10,543, types: 74,347, coercions: 16,504,630}
> *** Tidy Core:
> Result size of Tidy Core
> = {terms: 10,846, types: 75,522, coercions: 16,504,729}
> *** CorePrep:
> Result size of CorePrep
> = {terms: 14,823, types: 96,430, coercions: 16,504,729}
> *** ByteCodeGen:
> Upsweep completely successful.
> *** Deleting temp files:
> Warning: deleting non-existent
> /var/folders/y9/km24zv3d4yl711mwv85vwljc0000gp/T/ghc64965_0/ghc_95.c
> Warning: deleting non-existent
> /var/folders/y9/km24zv3d4yl711mwv85vwljc0000gp/T/ghc64965_0/ghc_94.o
> Ok, modules loaded: Prologue, Type.Bool, Type.Container, Type.List,
> Type.Set, Data.Cata, Type.Promotion, Data.Bits.Mask,
> Control.Monad.State.Dependent, Control.Monad.Poly,
> Control.Applicative.Poly, Type.Regex, Type.Either, Data.Reprx,
> Data.Impossible, Type.Cache.TH, Main, Control.Lens.Utils,
> Control.Lens.Wrapped.Utils, Data.Text.CodeBuilder,
> Data.Text.CodeBuilder.Tok, Data.Text.CodeBuilder.Builder,
> Data.Text.CodeBuilder.Doc, Data.Binary.Instances.Missing,
> Data.Default.Instances.Missing, Data.String.Class, Data.Text.Class,
> Data.Convert, Data.Layer, Data.Container.Class, Data.Container.List,
> Data.Functor.Utils, Type.Operators, Type.Show, Type.Wrapped,
> Data.Container.Opts, Data.Container.Poly, Data.Convert.Base,
> Data.Convert.Instances, Data.Convert.Instances.Map,
> Data.Convert.Instances.Num, Data.Convert.Instances.Text,
> Data.Convert.Instances.TH, Data.Convert.Bound, Data.Bits.Base.
> *** Parser:
> *** Desugar:
> *** Simplify:
> *** CorePrep:
> *** ByteCodeGen:
> ...
> }}}
>
> and with type families:
>
> {{{
> *** Parser:
> *** Renamer/typechecker:
> *** Desugar:
> Result size of Desugar (after optimization)
> = {terms: 310, types: 867, coercions: 78}
> *** Simplifier:
> Result size of Simplifier iteration=1
> = {terms: 301, types: 878, coercions: 296}
> Result size of Simplifier
> = {terms: 301, types: 878, coercions: 293}
> *** Tidy Core:
> Result size of Tidy Core
> = {terms: 337, types: 1,002, coercions: 293}
> *** CorePrep:
> Result size of CorePrep
> = {terms: 475, types: 1,305, coercions: 293}
> *** ByteCodeGen:
> *** Deleting temp files:
> Warning: deleting non-existent
> /var/folders/y9/km24zv3d4yl711mwv85vwljc0000gp/T/ghc64863_0/ghc_93.c
> Warning: deleting non-existent
> /var/folders/y9/km24zv3d4yl711mwv85vwljc0000gp/T/ghc64863_0/ghc_92.o
> compile: input file
> /var/folders/y9/km24zv3d4yl711mwv85vwljc0000gp/T/ghc64863_0/ghc_1.hscpp
> *** Checking old interface for Main:
> [45 of 45] Compiling Main (
> /Users/wdanilo/dev/hs/public/variants/Main.hs, interpreted )
> *** Parser:
> *** Renamer/typechecker:
> *** Desugar:
> Result size of Desugar (after optimization)
> = {terms: 10,303, types: 67,609, coercions: 162,249}
> *** Simplifier:
> Result size of Simplifier iteration=1
> = {terms: 10,722, types: 75,721, coercions: 323,027}
> Result size of Simplifier iteration=2
> = {terms: 10,550, types: 74,767, coercions: 320,473}
> Result size of Simplifier iteration=3
> = {terms: 10,543, types: 74,677, coercions: 320,437}
> Result size of Simplifier
> = {terms: 10,543, types: 74,677, coercions: 320,333}
> *** Tidy Core:
> Result size of Tidy Core
> = {terms: 10,846, types: 75,852, coercions: 320,432}
> *** CorePrep:
> Result size of CorePrep
> = {terms: 14,823, types: 96,760, coercions: 320,432}
> *** ByteCodeGen:
> Upsweep completely successful.
> *** Deleting temp files:
> Warning: deleting non-existent
> /var/folders/y9/km24zv3d4yl711mwv85vwljc0000gp/T/ghc64863_0/ghc_95.c
> Warning: deleting non-existent
> /var/folders/y9/km24zv3d4yl711mwv85vwljc0000gp/T/ghc64863_0/ghc_94.o
> Ok, modules loaded: Prologue, Type.Bool, Type.Container, Type.List,
> Type.Set, Data.Cata, Type.Promotion, Data.Bits.Mask,
> Control.Monad.State.Dependent, Control.Monad.Poly,
> Control.Applicative.Poly, Type.Regex, Type.Either, Data.Reprx,
> Data.Impossible, Type.Cache.TH, Main, Control.Lens.Utils,
> Control.Lens.Wrapped.Utils, Data.Text.CodeBuilder,
> Data.Text.CodeBuilder.Tok, Data.Text.CodeBuilder.Builder,
> Data.Text.CodeBuilder.Doc, Data.Binary.Instances.Missing,
> Data.Default.Instances.Missing, Data.String.Class, Data.Text.Class,
> Data.Convert, Data.Layer, Data.Container.Class, Data.Container.List,
> Data.Functor.Utils, Type.Operators, Type.Show, Type.Wrapped,
> Data.Container.Opts, Data.Container.Poly, Data.Convert.Base,
> Data.Convert.Instances, Data.Convert.Instances.Map,
> Data.Convert.Instances.Num, Data.Convert.Instances.Text,
> Data.Convert.Instances.TH, Data.Convert.Bound, Data.Bits.Base.
> *** Parser:
> *** Desugar:
> *** Simplify:
> *** CorePrep:
> *** ByteCodeGen:
> ...
> }}}
>
> As we can see the type aliases produce much more coertions: 16,383,834 vs
> 78 using type families. This is really interesting thing and it seems
> related to the linked bug above.
New description:
Hello guys! This bug is awkard at last to me. So I notiiced today, that
using type aliases in my code takes twice as long to copile than using
closed type families with just single member. So to be most precise - when
I replace the following line:
{{{
type XQ1 m a = Targets (Match m a)
}}}
with
{{{
type family XQ1 m a where XQ1 m a = Targets (Match m a)
}}}
the compilation time drops from 15s to 7s (this type alias is heavily used
across the application). I think it could be somehow related to the famous
#8095 bug, but I can of course be wrong here.
Unfortunetally the codebase is pretty big and its not so easy to make a
minimal example, but I'll try to work on it during the upcoming weekend
(please notify me if that would not be necessary).
And some statistics from `-dshow-passes`:
When using type alias:
{{{
*** Parser:
*** Renamer/typechecker:
*** Desugar:
Result size of Desugar (after optimization)
= {terms: 10,303, types: 66,949, coercions: 16,383,834}
*** Simplifier:
Result size of Simplifier iteration=1
= {terms: 10,722, types: 75,391, coercions: 16,507,338}
Result size of Simplifier iteration=2
= {terms: 10,550, types: 74,437, coercions: 16,504,770}
Result size of Simplifier iteration=3
= {terms: 10,543, types: 74,347, coercions: 16,504,734}
Result size of Simplifier
= {terms: 10,543, types: 74,347, coercions: 16,504,630}
*** Tidy Core:
Result size of Tidy Core
= {terms: 10,846, types: 75,522, coercions: 16,504,729}
*** CorePrep:
Result size of CorePrep
= {terms: 14,823, types: 96,430, coercions: 16,504,729}
*** ByteCodeGen:
Upsweep completely successful.
*** Deleting temp files:
Warning: deleting non-existent
/var/folders/y9/km24zv3d4yl711mwv85vwljc0000gp/T/ghc64965_0/ghc_95.c
Warning: deleting non-existent
/var/folders/y9/km24zv3d4yl711mwv85vwljc0000gp/T/ghc64965_0/ghc_94.o
Ok, modules loaded: Prologue, Type.Bool, Type.Container, Type.List,
Type.Set, Data.Cata, Type.Promotion, Data.Bits.Mask,
Control.Monad.State.Dependent, Control.Monad.Poly,
Control.Applicative.Poly, Type.Regex, Type.Either, Data.Reprx,
Data.Impossible, Type.Cache.TH, Main, Control.Lens.Utils,
Control.Lens.Wrapped.Utils, Data.Text.CodeBuilder,
Data.Text.CodeBuilder.Tok, Data.Text.CodeBuilder.Builder,
Data.Text.CodeBuilder.Doc, Data.Binary.Instances.Missing,
Data.Default.Instances.Missing, Data.String.Class, Data.Text.Class,
Data.Convert, Data.Layer, Data.Container.Class, Data.Container.List,
Data.Functor.Utils, Type.Operators, Type.Show, Type.Wrapped,
Data.Container.Opts, Data.Container.Poly, Data.Convert.Base,
Data.Convert.Instances, Data.Convert.Instances.Map,
Data.Convert.Instances.Num, Data.Convert.Instances.Text,
Data.Convert.Instances.TH, Data.Convert.Bound, Data.Bits.Base.
*** Parser:
*** Desugar:
*** Simplify:
*** CorePrep:
*** ByteCodeGen:
...
}}}
and with type families:
{{{
*** Parser:
*** Renamer/typechecker:
*** Desugar:
Result size of Desugar (after optimization)
= {terms: 10,303, types: 67,609, coercions: 162,249}
*** Simplifier:
Result size of Simplifier iteration=1
= {terms: 10,722, types: 75,721, coercions: 323,027}
Result size of Simplifier iteration=2
= {terms: 10,550, types: 74,767, coercions: 320,473}
Result size of Simplifier iteration=3
= {terms: 10,543, types: 74,677, coercions: 320,437}
Result size of Simplifier
= {terms: 10,543, types: 74,677, coercions: 320,333}
*** Tidy Core:
Result size of Tidy Core
= {terms: 10,846, types: 75,852, coercions: 320,432}
*** CorePrep:
Result size of CorePrep
= {terms: 14,823, types: 96,760, coercions: 320,432}
*** ByteCodeGen:
Upsweep completely successful.
*** Deleting temp files:
Warning: deleting non-existent
/var/folders/y9/km24zv3d4yl711mwv85vwljc0000gp/T/ghc64863_0/ghc_95.c
Warning: deleting non-existent
/var/folders/y9/km24zv3d4yl711mwv85vwljc0000gp/T/ghc64863_0/ghc_94.o
Ok, modules loaded: Prologue, Type.Bool, Type.Container, Type.List,
Type.Set, Data.Cata, Type.Promotion, Data.Bits.Mask,
Control.Monad.State.Dependent, Control.Monad.Poly,
Control.Applicative.Poly, Type.Regex, Type.Either, Data.Reprx,
Data.Impossible, Type.Cache.TH, Main, Control.Lens.Utils,
Control.Lens.Wrapped.Utils, Data.Text.CodeBuilder,
Data.Text.CodeBuilder.Tok, Data.Text.CodeBuilder.Builder,
Data.Text.CodeBuilder.Doc, Data.Binary.Instances.Missing,
Data.Default.Instances.Missing, Data.String.Class, Data.Text.Class,
Data.Convert, Data.Layer, Data.Container.Class, Data.Container.List,
Data.Functor.Utils, Type.Operators, Type.Show, Type.Wrapped,
Data.Container.Opts, Data.Container.Poly, Data.Convert.Base,
Data.Convert.Instances, Data.Convert.Instances.Map,
Data.Convert.Instances.Num, Data.Convert.Instances.Text,
Data.Convert.Instances.TH, Data.Convert.Bound, Data.Bits.Base.
*** Parser:
*** Desugar:
*** Simplify:
*** CorePrep:
*** ByteCodeGen:
...
}}}
As we can see the type aliases produce much more coertions: 16,383,834 vs
162,249 using type families. This is really interesting thing and it seems
related to the linked bug above.
--
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11375#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list