Re: [GHC] #5926: Add strict versions of modifyIORef and atomicModifyIORef

2012-09-18 Thread GHC
#5926: Add strict versions of modifyIORef and atomicModifyIORef
--+-
  Reporter:  joeyadams|  Owner:  simonmar
  Type:  feature request  | Status:  closed  
  Priority:  normal   |  Milestone:  7.6.1   
 Component:  libraries/base   |Version:  7.4.1   
Resolution:  fixed|   Keywords:  
Os:  Unknown/Multiple |   Architecture:  Unknown/Multiple
   Failure:  Runtime performance bug  | Difficulty:  Unknown 
  Testcase:   |  Blockedby:  
  Blocking:   |Related:  
--+-

Comment(by dons):

 For historical reference, see this 2009 thread on the issue (I was trying
 to find this thread, but google doesn't seem to like to index it).

 * [http://www.haskell.org/pipermail/haskell-cafe/2009-June/063137.html
 IORef memory leak]

-- 
Ticket URL: http://hackage.haskell.org/trac/ghc/ticket/5926#comment:3
GHC http://www.haskell.org/ghc/
The Glasgow Haskell Compiler

___
Glasgow-haskell-bugs mailing list
Glasgow-haskell-bugs@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs


Re: [GHC] #5926: Add strict versions of modifyIORef and atomicModifyIORef

2012-03-28 Thread GHC
#5926: Add strict versions of modifyIORef and atomicModifyIORef
--+-
  Reporter:  joeyadams|  Owner:  simonmar
  Type:  feature request  | Status:  closed  
  Priority:  normal   |  Milestone:  7.6.1   
 Component:  libraries/base   |Version:  7.4.1   
Resolution:  fixed|   Keywords:  
Os:  Unknown/Multiple |   Architecture:  Unknown/Multiple
   Failure:  Runtime performance bug  | Difficulty:  Unknown 
  Testcase:   |  Blockedby:  
  Blocking:   |Related:  
--+-
Changes (by simonmar):

  * status:  new = closed
  * resolution:  = fixed


Comment:

 {{{
 commit 531c09ed708b394c43775c2e07f14a39256bc498
 Author: Joey Adams joeyadams3.14...@gmail.com
 Date:   Sat Mar 10 19:15:40 2012 -0500

 Add strict versions of modifyIORef and atomicModifyIORef
 }}}

-- 
Ticket URL: http://hackage.haskell.org/trac/ghc/ticket/5926#comment:2
GHC http://www.haskell.org/ghc/
The Glasgow Haskell Compiler

___
Glasgow-haskell-bugs mailing list
Glasgow-haskell-bugs@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs


Re: [GHC] #5926: Add strict versions of modifyIORef and atomicModifyIORef

2012-03-14 Thread GHC
#5926: Add strict versions of modifyIORef and atomicModifyIORef
-+--
Reporter:  joeyadams |   Owner:  simonmar   
Type:  feature request   |  Status:  new
Priority:  normal|   Milestone:  7.6.1  
   Component:  libraries/base| Version:  7.4.1  
Keywords:|  Os:  Unknown/Multiple   
Architecture:  Unknown/Multiple  | Failure:  Runtime performance bug
  Difficulty:  Unknown   |Testcase: 
   Blockedby:|Blocking: 
 Related:|  
-+--
Changes (by simonmar):

  * owner:  = simonmar
  * difficulty:  = Unknown
  * milestone:  = 7.6.1


Comment:

 Ok, I'll apply your patch as is.  There's another variant of strict
 `atomicModifyIORef` that I have been wanting to experiment with:

 {{{
 atomicModifyIORef' :: IORef a - (a - (a,b)) - IO b
 atomicModifyIORef' (IORef (STRef r#)) f = IO $ \s0 - loop s0
   where
 loop s0 =
   case readMutVar# r# s0 of { (# s1, a #) -
   let !(a',b) = f a in
   case casMutVar# r# a a' s1 of { (# s2, ok, _ #) -
   case ok of { 0# - (# s2, b #); _ - loop s2 }}}
 }}}

 This is like a mini-STM transaction that evaluates `f a` and then attempts
 to compare-and-swap the result in.  Since evaluating `f a` might take an
 arbitrary amount of time, the CAS might fail, and we have to loop.  On the
 other hand, using this we can avoid ever writing thunks into the `IORef`,
 which avoids any problems with black holes.

-- 
Ticket URL: http://hackage.haskell.org/trac/ghc/ticket/5926#comment:1
GHC http://www.haskell.org/ghc/
The Glasgow Haskell Compiler

___
Glasgow-haskell-bugs mailing list
Glasgow-haskell-bugs@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs


[GHC] #5926: Add strict versions of modifyIORef and atomicModifyIORef

2012-03-10 Thread GHC
#5926: Add strict versions of modifyIORef and atomicModifyIORef
-+--
 Reporter:  joeyadams|  Owner:  
 Type:  feature request  | Status:  new 
 Priority:  normal   |  Component:  libraries/base  
  Version:  7.4.1|   Keywords:  
   Os:  Unknown/Multiple |   Architecture:  Unknown/Multiple
  Failure:  Runtime performance bug  |   Testcase:  
Blockedby:   |   Blocking:  
  Related:   |  
-+--
 It is easy to misuse modifyIORef and atomicModifyIORef due to their lack
 of strictness.  For example, if you use an IORef as a counter, use
 modifyIORef to increment it, and never evaluate the value until the very
 end, your program will leak memory, and you may even get a stack overflow:

 {{{
 ref - newIORef 0
 replicateM_ 100 $ modifyIORef ref (+1)
 readIORef ref = print
 }}}

 Today, I found a [https://github.com/vincenthz/hs-tls/pull/8 space leak in
 the tls package].  Repeatedly calling sendData would leak memory.  It
 didn't take me long to find the cause once I noticed a module named
 Measurement used for gathering connection statistics.  It used
 modifyIORef to update the Measurement structure.  When I changed it to
 this:

 {{{
 x - readIORef (ctxMeasurement ctx)
 writeIORef (ctxMeasurement ctx) $! f x
 }}}

 the space leak went away.

 A more subtle mistake can be made using atomicModifyIORef.  Can you spot
 the problem with this code?

 {{{
 atomicModifyIORef ref (\_ - (new_value, ()))
 }}}

 It's not incrementing anything, it's just replacing the value.  However,
 it's still deferring evaluation of the function.  This mistake was pointed
 out in [http://themonadreader.files.wordpress.com/2011/10/issue19.pdf The
 Monad.Reader Issue 19], where they suggested the following idiom:

 {{{
 x - atomicModifyIORef ref (\_ - (new_value, ()))
 x `seq` return ()
 }}}

 Thus, I believe there should be strict variants of modifyIORef and
 atomicModifyIORef, if only to warn programmers of these pitfalls.

 {{{modifyIORef'}}} is pretty straightforward: force the result of applying
 the function:

 {{{
 modifyIORef' ref f = do
 x - readIORef ref
 let x' = f x
 x' `seq` writeIORef ref x'
 }}}

 The only question is: would it be better to force `x'` after `writeIORef`
 instead of before it, in case a caller is trying to share the IORef among
 threads (which they shouldn't be)?

 {{{atomicModifyIORef}}} is less straightforward.  Should we force the
 values themselves?  It is possible to avoid the space leak above without
 forcing either the new value or the return value:

 {{{
 atomicModifyIORef' :: IORef a - (a - (a,b)) - IO b
 atomicModifyIORef' ref f = do
 p - atomicModifyIORef ref (\a - let p = f a in (fst p, p))
 p `seq` return (snd p)
 }}}

 It also allows {{{f}}} to decide what to force.  For example, with this
 definition of atomicModifyIORef', the following program prints 1000
 and does not leak memory:

 {{{
 ref - newIORef 0
 replicateM_ 1000 $
 atomicModifyIORef' ref
 (\n - let n' = n + 1
 in n' `seq` (n', undefined))
 readIORef ref = print
 }}}

 In the attached patch, I didn't implement atomicModifyIORef' this way.
 Instead, I made it force both the old and new values, and added a separate
 function called atomicWriteIORef that has the same signature as
 writeIORef, but is based on atomicModifyIORef.

 I believe the real value of such functions is to warn programmers about
 these pitfalls.

-- 
Ticket URL: http://hackage.haskell.org/trac/ghc/ticket/5926
GHC http://www.haskell.org/ghc/
The Glasgow Haskell Compiler

___
Glasgow-haskell-bugs mailing list
Glasgow-haskell-bugs@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs