[GHC] #13253: Exponential compilation time with RWST & ReaderT stack with `-02`

GHC ghc-devs at haskell.org
Tue Oct 2 12:59:45 UTC 2018


#13253: Exponential compilation time with RWST & ReaderT stack with `-02`
-------------------------------------+-------------------------------------
        Reporter:  phadej            |                Owner:  bgamari, osa1
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:  8.8.1
       Component:  Compiler          |              Version:  8.0.1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Compile-time      |  Unknown/Multiple
  performance bug                    |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  #15630            |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by tdammers):

 I've managed to simplify it further:

 {{{#!haskell
 module LessBad where

 import Data.ByteString (ByteString)
 import qualified Data.ByteString.Char8 as Char8

 data HugeStruct = HugeStruct
   !ByteString
   !ByteString
   !ByteString
   !ByteString
   !ByteString
   !ByteString
   !ByteString
   !ByteString
   !ByteString -- 9th

 data FormResult a = FormMissing
                   | FormFailure [ByteString]
                   | FormSuccess a
     deriving Show

 formMap _ FormMissing = FormMissing
 formMap _ (FormFailure errs) = FormFailure errs
 formMap f (FormSuccess a) = FormSuccess $ f a
 infixl 4 `formMap`

 formAp :: FormResult (a -> b) -> FormResult a -> FormResult b
 (FormSuccess f) `formAp` (FormSuccess g) = FormSuccess $ f g
 (FormFailure x) `formAp` (FormFailure y) = FormFailure $ x ++ y
 (FormFailure x) `formAp` _ = FormFailure x
 _ `formAp` (FormFailure y) = FormFailure y
 _ `formAp` _ = FormMissing
 infixl 4 `formAp`


 mreq :: String -> IO (FormResult ByteString, ())
 mreq v = mhelper v (\m l -> FormFailure [Char8.pack "fail"]) FormSuccess

 askParams :: IO (Maybe [(String, ByteString)])
 askParams = do
     return $ Just []

 mhelper
     :: String
     -> (() -> () -> FormResult b)   -- on missing
     -> (ByteString -> FormResult b) -- on success
     -> IO (FormResult b, ())
 mhelper v onMissing onFound = do
     mp <- askParams
     (res, x) <- case mp of
         Nothing -> return (FormMissing, ())
         Just p -> do
             return $ case lookup v p of
                 Nothing -> (onMissing () (), ())
                 Just t -> (onFound t, ())
     return (res, x)

 -- Either of these fixes the blowup
 -- {-# NOINLINE mreq #-}
 -- {-# NOINLINE mhelper #-}
 -- {-# NOINLINE formMap #-}

 sampleForm2 :: IO (FormResult HugeStruct)
 sampleForm2 = do
     (x01, _) <- mreq "UNUSED"
     (x02, _) <- mreq "UNUSED"
     (x03, _) <- mreq "UNUSED"
     (x04, _) <- mreq "UNUSED"
     (x05, _) <- mreq "UNUSED"
     (x06, _) <- mreq "UNUSED"
     (x07, _) <- mreq "UNUSED"
     (x08, _) <- mreq "UNUSED"
     (x09, _) <- mreq "UNUSED"

     let hugeStructRes = HugeStruct
           `formMap` x01
           `formAp`  x02
           `formAp`  x03
           `formAp`  x04
           `formAp`  x05
           `formAp`  x06
           `formAp`  x07
           `formAp`  x08
           `formAp`  x09

     return hugeStructRes
 }}}

 There are hardly any constraints left to specialize here, except the
 `Monad` instance for `IO`. And indeed, changing all those `IO` into `Monad
 m => m` gets compilation times down from almost a minute to under one
 second.

 So for some reason, specializing the monadic binds and / or returns for
 `IO` here increases code size by a factor of almost 50:

 {{{
 Result size of Simplifier
   = {terms: 6,615, types: 5,827, coercions: 39, joins: 8/70}
 !!! Simplifier [LessBad]: finished in 950.46 milliseconds, allocated
 1067.498 megabytes
 *** SpecConstr [LessBad]:
 Result size of SpecConstr
   = {terms: 286,335, types: 251,655, coercions: 39, joins: 960/5,435}
 !!! SpecConstr [LessBad]: finished in 10107.67 milliseconds, allocated
 10077.732 megabytes
 }}}

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13253#comment:39>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list