[Haskell-cafe] Space leak with unsafePerformIO
Henning Thielemann
lemming at henning-thielemann.de
Sun Jun 27 12:59:42 EDT 2010
On Sun, 27 Jun 2010, Bertram Felgenhauer wrote:
> If the compiler had produced
>
> Main.lvl3 =
> case Main.ds of wild_Xw { (prefix_aCf, suffix_aCh) ->
> suffix_aCh
> }
>
> Main.lvl4 = Main.go1 Main.lvl3
>
> instead, then there would not be a leak. This whole record selector
> thunk business is very fragile.
Bertram, thank you a lot for the detailed analysis! It seems that I have
stepped into a nasty implementation detail of GHC.
> The good news is that the problem is completely unrelated to
> unsafePerformIO (the presence of unsafePerformIO makes optimisations
> more difficult, but any pure function of sufficient complexity would
> have the same effect).
>
> There's a simple fix for the problem, too: Change
>
>> let (prefix, suffix) = makeTwoLists 'a'
>
> to
> let !(prefix, suffix) = makeTwoLists 'a'
>
> in which case the compiler produces code similar to the non-leaky case
> for all alternatives.
Actually this fix works for my example program and another one that is
based on chunky StorableVector. But when I switch off profiling the
StorableVector example runs into a space leak, again, while the one with
plain lists that I have sent here still works. I'll investigate into this,
but it seems indeed very fragile and I wonder whether there is a more
reliable way.
Maybe I can combine splitAtLazy and (++) to a function like
splitAtAndAppend :: [x] -> ([a] -> [b]) -> ([a] -> [b]) -> [a] -> [b]
but I'm afraid I will need pairs temporarily and then I run into the same
problems.
More information about the Haskell-Cafe
mailing list