Re: [Haskell-cafe] help diagnosing space leak with IORef/STRef, just incrementing a million times.

2013-01-06 Thread Christopher Done
A similar use-case and same solution with IORefs:
http://hpaste.org/diff/80055/80058 Guess which one threw a
stackoverflow and which one ran indefinitely when given a few hundred
million lines of input.

On 7 January 2013 07:35, Albert Y. C. Lai  wrote:
> On 13-01-07 12:12 AM, Thomas Hartman wrote:
>>
>> I have a space leak in a function that increments a number inside
>> IORef or STRef (either lazy or strict).
>
>
> IORef and STRef operations do not automatically evaluate contents.
> "writeIORef r (x + 1)" simply stores a pointer to the expression (thunk) "x
> + 1" into the mutable cell. readIORef just reports back a pointer.
> modifyIORef just calls readIORef and writeIORef. No evaluation throughout.
>
> "modifyIORef incr" where
>
> incr !x = x + 1
>
> does not make a difference because it is just "writeIORef r (incr x))",
> i.e., simply stores a pointer to the expression (thunk) "incr x" into the
> mutable cell. The whole process doesn't even care about how many bangs are
> in incr.
>
> (It is illuminating to consider how "const True (incr x)" does not evaluate
> x. A pointer to True and a pointer to "incr x" are passed to const, then
> const throws away the latter without even looking. See also "const True
> undefined". One day, you will thank "writeIORef r undefined"; I certainly
> did.)
>
> Same for both Data.STRef.Strict and Data.STRef.Lazy. They do not mean what
> you think. Here is what they mean:
>
> Data.STRef.Strict means what Control.Monad.ST.Strict means
> Data.STRef.Lazy means what Control.Monad.ST.Lazy means
>
> Control.Monad.ST.Strict means that the following hangs:
>
> x = head (runST list) where
>   list :: ST s [Bool]
>   list = do {xs <- list; return (True : xs)}
>
> Control.Monad.ST.Lazy means that the above terminates and gives the answer
> True.
>
> (Up to this point, same story for Control.Monad.State.Strict and
> Control.Monad.State.Lazy.)
>
> I still have not understood Control.Monad.ST.Lazy enough to articulate its
> full semantics, but I have some more examples to show what it does:
>
> http://hpaste.org/63925
>
> By understanding what "Lazy" in Control.Monad.ST.Lazy means, you also see
> what "Strict" does *not* mean.
>
> In IO or Control.Monad.ST.Strict, use
>
>   let y = x+1 in y `seq` write[IO/ST]Ref r y
>
> to expedite the evaluation of x+1. Using the same idea, you may write your
> own modify[IO/ST]RefNOW to evaluate while updating.
>
>
> ___
> Haskell-Cafe mailing list
> Haskell-Cafe@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] help diagnosing space leak with IORef/STRef, just incrementing a million times.

2013-01-06 Thread Thomas Bereknyei
I have had issues like this with modifySTRef before. Try to make a strict
version modifySTRef'

If memory serves, something like this worked for me.
modifySTRef' r f =
  do
a <- readSTRef r
writeSTRef r $! f a
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] help diagnosing space leak with IORef/STRef, just incrementing a million times.

2013-01-06 Thread Albert Y. C. Lai

On 13-01-07 12:12 AM, Thomas Hartman wrote:

I have a space leak in a function that increments a number inside
IORef or STRef (either lazy or strict).


IORef and STRef operations do not automatically evaluate contents. 
"writeIORef r (x + 1)" simply stores a pointer to the expression (thunk) 
"x + 1" into the mutable cell. readIORef just reports back a pointer. 
modifyIORef just calls readIORef and writeIORef. No evaluation throughout.


"modifyIORef incr" where

incr !x = x + 1

does not make a difference because it is just "writeIORef r (incr x))", 
i.e., simply stores a pointer to the expression (thunk) "incr x" into 
the mutable cell. The whole process doesn't even care about how many 
bangs are in incr.


(It is illuminating to consider how "const True (incr x)" does not 
evaluate x. A pointer to True and a pointer to "incr x" are passed to 
const, then const throws away the latter without even looking. See also 
"const True undefined". One day, you will thank "writeIORef r 
undefined"; I certainly did.)


Same for both Data.STRef.Strict and Data.STRef.Lazy. They do not mean 
what you think. Here is what they mean:


Data.STRef.Strict means what Control.Monad.ST.Strict means
Data.STRef.Lazy means what Control.Monad.ST.Lazy means

Control.Monad.ST.Strict means that the following hangs:

x = head (runST list) where
  list :: ST s [Bool]
  list = do {xs <- list; return (True : xs)}

Control.Monad.ST.Lazy means that the above terminates and gives the 
answer True.


(Up to this point, same story for Control.Monad.State.Strict and 
Control.Monad.State.Lazy.)


I still have not understood Control.Monad.ST.Lazy enough to articulate 
its full semantics, but I have some more examples to show what it does:


http://hpaste.org/63925

By understanding what "Lazy" in Control.Monad.ST.Lazy means, you also 
see what "Strict" does *not* mean.


In IO or Control.Monad.ST.Strict, use

  let y = x+1 in y `seq` write[IO/ST]Ref r y

to expedite the evaluation of x+1. Using the same idea, you may write 
your own modify[IO/ST]RefNOW to evaluate while updating.


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe