
#13080: Memory leak caused by nested monadic loops -------------------------------------+------------------------------------- Reporter: Feuerbach | Owner: Type: bug | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 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):
I thought that the state hack doesn't change the arity of functions, just marks them single-entry.
That’s how it works, but the ultimate goal of the state hack (the way I see it) is to eta-expand them. Usually this works by treating a `State#`-typed lambda as one-shot: {{{ foo = bar x >> baz y }}} will, after inlining `>>` (if that happens, but it usually does for IO) look like this: {{{ foo = let a = bar x b = baz y in \s0 -> case a s0 of (_,s1) -> b s1 }}} which is usually bad because of the allocations of `a` and `b`. (But I say “usually” because it is good if `bar x` is expensive and `foo` is used many times – these are the instances when people complain about the state hack removing this sharing). Now because `s0` is treated as one-shot, two optimizations are enabled, both of which have ultimately the same effect: * The inliner feels empowered to inline `a` and `b` into the lambda, because it is one shot. Then we obtain {{{ foo = \s0 -> case bar x s0 of (_,s1) -> baz y s1 }}} which we want. * The arity analysis uses the one-shot information on the lambda to determine that `foo` has arity 1 and eta-expands it: {{{ foo = \s -> (let a = bar x b = baz y in \s0 -> case a s0 of (_,s1) -> b s1) s }}} which then gets simplified to {{{ foo = \s -> case bar x s of (_,s1) -> baz y s1 }}} again. I once had an idea for a less intrusive state hack variant which would do this eta-expansion directly (but otherwise do not meddle with the one- shotness of `State#`-typed lambdas, which can be wrong), but did not follow through with it. See [ticket:9388#comment:6] for some background. But this is all `State#`-specific, while your bug is about abstractly monad code, where the compiler may now use knowledge about `IO`’s bind, right? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13080#comment:13 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler