diff options
author | Bartosz Nitka <niteria@gmail.com> | 2018-01-05 15:20:05 +0000 |
---|---|---|
committer | Bartosz Nitka <niteria@gmail.com> | 2018-01-10 13:50:56 +0000 |
commit | dbdf77d92c9cd0bbb269137de0bf8754573cdc1e (patch) | |
tree | 17bbe7fb388308615ba009e4f887c719c9e58107 /compiler/prelude/TysWiredIn.hs | |
parent | 1577908f2a9db0fcf6f749d40dd75481015f5497 (diff) | |
download | haskell-dbdf77d92c9cd0bbb269137de0bf8754573cdc1e.tar.gz |
Lift constructor tag allocation out of a loop
Before this change, for each constructor that we want
to allocate a tag for we would traverse a list of all
the constructors in a datatype to determine which tag
a constructor should get.
This is obviously quadratic and for datatypes with 10k
constructors it actually makes a big difference.
This change implements the plan outlined by @simonpj in
https://mail.haskell.org/pipermail/ghc-devs/2017-October/014974.html
which is basically about using a map and constructing it outside the
loop.
One place where things got a bit awkward was TysWiredIn.hs,
it would have been possible to just assign the tags by hand, but
that seemed error-prone to me, so I decided to go through a map
there as well.
Test Plan:
./validate
On a file with 10k constructors
Before:
8,130,522,344 bytes allocated in the heap
Total time 3.682s ( 3.920s elapsed)
After:
4,133,478,744 bytes allocated in the heap
Total time 2.509s ( 2.750s elapsed)
Reviewers: simonpj, bgamari
Reviewed By: simonpj
Subscribers: goldfire, rwbarton, thomie, simonmar, carter, simonpj
GHC Trac Issues: #14657
Differential Revision: https://phabricator.haskell.org/D4289
Diffstat (limited to 'compiler/prelude/TysWiredIn.hs')
-rw-r--r-- | compiler/prelude/TysWiredIn.hs | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/compiler/prelude/TysWiredIn.hs b/compiler/prelude/TysWiredIn.hs index fda6b221f3..72c24edc3c 100644 --- a/compiler/prelude/TysWiredIn.hs +++ b/compiler/prelude/TysWiredIn.hs @@ -150,7 +150,7 @@ import TyCon import Class ( Class, mkClass ) import RdrName import Name -import NameEnv ( NameEnv, mkNameEnv, lookupNameEnv ) +import NameEnv ( NameEnv, mkNameEnv, lookupNameEnv, lookupNameEnv_NF ) import NameSet ( NameSet, mkNameSet, elemNameSet ) import BasicTypes ( Arity, Boxity(..), TupleSort(..), ConTagZ, SourceText(..) ) @@ -517,6 +517,13 @@ pcDataConWithFixity' declared_infix dc_name wrk_key rri tyvars ex_tyvars user_tyvars arg_tys tycon = data_con where + tag_map = mkTyConTagMap tycon + -- This constructs the constructor Name to ConTag map once per + -- constructor, which is quadratic. It's OK here, because it's + -- only called for wired in data types that don't have a lot of + -- constructors. It's also likely that GHC will lift tag_map, since + -- we call pcDataConWithFixity' with static TyCons in the same module. + -- See Note [Constructor tag allocation] and #14657 data_con = mkDataCon dc_name declared_infix prom_info (map (const no_bang) arg_tys) [] -- No labelled fields @@ -527,6 +534,7 @@ pcDataConWithFixity' declared_infix dc_name wrk_key rri arg_tys (mkTyConApp tycon (mkTyVarTys tyvars)) rri tycon + (lookupNameEnv_NF tag_map dc_name) [] -- No stupid theta (mkDataConWorkId wrk_name data_con) NoDataConRep -- Wired-in types are too simple to need wrappers |