[GHC] #11271: Costly let binding gets duplicated in IO action value
#11271: Costly let binding gets duplicated in IO action value -------------------------------------+------------------------------------- Reporter: dramforever | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.2 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: Runtime Unknown/Multiple | performance bug Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- The following code is much slower when optimized. {{{#!hs module Main where import Control.Monad import Data.Char import System.IO -- getInt: read a integer from stdin, skipping spaces {-# NOINLINE getInt #-} -- to simplify generated core getInt :: IO Int getInt = skipSpaces >> go 0 where skipSpaces = do next <- hLookAhead stdin if isSpace next then getChar >> skipSpaces else return () go n = do next <- hLookAhead stdin if isNumber next then getChar >> go (10 * n + digitToInt next) else return n {-# NOINLINE generateSlowList #-} generateSlowList :: Int -> [Int] generateSlowList 0 = [1] generateSlowList n = scanl (+) 1 (generateSlowList (n-1)) main = do n <- getInt let ls = generateSlowList n --- !!! replicateM_ n $ do i <- getInt print (ls !! i) }}} How to run: {{{ (echo 10000; yes 5000) | time ./slow > /dev/null }}} After a rough look through the generated core, it seems that the `ls` was moved into the argument to `replicateM_`, which is a lambda taking a `State# RealWorld`. It means that a list is rebuilt every time it's indexed, even though a let binding could have caused sharing. By the way it seems that `-fno-state-hack`, which seems related, doesn't seem to help. Interesting to note that using a bang pattern (`let !ls = ...`) would make the problem go away. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11271> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#11271: Costly let binding gets duplicated in IO action value -------------------------------------+------------------------------------- Reporter: dramforever | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Runtime | Unknown/Multiple performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by nomeata): With 7.8, this is reproducable, but there, `-fno-state-hack` _does_ amend the problem. I think the reason is that since 7.10, interface files leak information about one-shot lambdas. This is intentional, but it means that the effect of `-fstate-hack` is less local. In particular, in this case, we have this in the interface of `System.IO`: {{{ f6fca8f374be656f4987fa89a8843dac print :: Show a => a -> IO () {- Arity: 3, Strictness: <L,1*U(A,1*C1(U),A)><L,U><L,U>, Unfolding: InlineRule (0, True, True) print1 `cast` (forall a. <Show a>_R ->_R <a>_R ->_R Sym (NTCo:IO[0] <()>_R)) -} 26b6b5cf5870ccc833912748cf8c9456 print1 :: Show a => a -> State# RealWorld -> (# State# RealWorld, () #) {- Arity: 3, Strictness: <L,1*U(A,1*C1(U),A)><L,U><L,U>, Unfolding: InlineRule (3, True, False) (\ @ a $dShow :: Show a x :: a eta :: State# RealWorld[OneShot] -> hPutStr2 stdout (show @ a $dShow x) True eta) -} }}} where the real-world argument is marked as `OneShot`. Without digging deeper, I could imagine that this flag will make GHC believe that the whole argument to `replicateM_` is one shot and hence inline `ls` into it. The ideas in #9388 should amend this problem, but I was stalled there by performance regressions. But maybe we should just take the plunge, get rid of the state hack in its current form, get a more correct compiler, live with the performance regressions due to that and try to make up for it in other ways. Not sure though. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11271#comment:1> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#11271: Costly let binding gets duplicated in IO action value -------------------------------------+------------------------------------- Reporter: dramforever | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Runtime | Unknown/Multiple performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): See #1168 which is the master ticket for this problem -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11271#comment:2> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
participants (1)
-
GHC