[GHC] #13080: Memory leak caused by nested monadic loops
GHC
ghc-devs at haskell.org
Wed Jan 11 22:09:28 UTC 2017
#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
More information about the ghc-tickets
mailing list