<div dir="ltr">I made a few modifications to your code, and found that replacing `return (x3' + x4')` with `return $! x3' + x4'` reduced maximum residency down to 64kb. This forces evaluation earlier. You can see the progression here:<div><br></div><div><a href="https://gist.github.com/snoyberg/6a48876aedb9b19c808a0c53e86109ac">https://gist.github.com/snoyberg/6a48876aedb9b19c808a0c53e86109ac</a><br></div><div><br></div><div>I took it one step further, and used the mutable-containers package to use an unboxed reference instead of the boxed STRef type. In other words: it avoids allocating a heap object. Here's that version of the code:</div><div><br></div><div><div>#!/usr/bin/env stack</div><div>-- stack --resolver lts-7.14 --install-ghc exec --package mutable-containers -- ghc -O2 -with-rtsopts=-s</div><div>import <a href="http://Control.Monad.ST">Control.Monad.ST</a></div><div>import Data.Mutable</div><div><br></div><div>a :: Int</div><div> -> ST s Int</div><div> -> ST s Int</div><div> -> ST s Int</div><div> -> ST s Int</div><div> -> ST s Int</div><div> -> ST s Int</div><div>a k x1 x2 x3 x4 x5 =</div><div> do kk <- fmap asURef $ newRef k</div><div> let b = do k0 <- readRef kk</div><div> let k1 = k0 - 1</div><div> writeRef kk k1</div><div> a k1 b x1 x2 x3 x4</div><div> if k <= 0 then do x3' <- x3; x4' <- x4; return $! x3' + x4'</div><div> else do x5' <- x5; b' <- b; return $! x5' + b'</div><div><br></div><div>main = print (runST (a 22 (return 1) (return (-1)) (return (-1)) (return 1) (return 0)))</div></div><div><br></div><div>It knocked down total allocations from 2.7GB to 1.8GB, which is an improvement, but I think there's still some more low hanging fruit here.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jan 26, 2017 at 12:26 PM, Antoine Rimlet <span dir="ltr"><<a href="mailto:antoine.rimlet@gmail.com" target="_blank">antoine.rimlet@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi list,<div><br></div><div>I try to get the following little program (a slightly modified "Man or boy", it prints -14254067) work "as expected", that is, without consuming lots of memory:</div><div><br></div><div><div> import <a href="http://Control.Monad.ST" target="_blank">Control.Monad.ST</a></div><div> import Data.STRef</div><div> a k x1 x2 x3 x4 x5 =</div><div> do kk <- newSTRef k</div><div> let b = do k <- modifySTRef kk pred >> readSTRef kk; a k b x1 x2 x3 x4</div><div> if k <= 0 then do x3' <- x3; x4' <- x4; return (x3' + x4')</div><div> else do x5' <- x5; b' <- b; return (x5' + b')</div><div> main = print (runST (a 22 (return 1) (return (-1)) (return (-1)) (return 1) (return 0)))</div></div><div><br></div><div>I use GHC 7.8.4, and executing this program uses about 2.5 GB of memory (or about 3.5 GB with runghc). However, the "equivalent" program in OCaml only needs 4 MB (or 9 MB with the interpreter):</div><div><div><br></div><div>let rec a k x1 x2 x3 x4 x5 =</div><div> let kk = ref k in let rec b () = begin decr kk; a !kk b x1 x2 x3 x4 end</div><div> in if k <= 0 then let v = x3 () in v + x4 () else let v = x5 () in v + b ();;</div><div>print_int (a 22 (fun () -> 1) (fun () -> -1) (fun () -> -1) (fun () -> 1) (fun () -> 0));; print_newline ();;</div></div><div><br></div><div>Therefore I suspect I'm doing something wrong, but I can't see what. I did try to use the strict version modifySTRef' as indicated in the manual, but with no visible improvement.</div><div><br></div><div>Thanks,</div><div><br></div><div>Antoine</div><div><br></div></div>
<br>______________________________<wbr>_________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/haskell-<wbr>cafe</a><br>
Only members subscribed via the mailman list are allowed to post.<br></blockquote></div><br></div>