[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