[Haskell-cafe] Re: Long running Haskell program

2009-11-12 Thread Heinrich Apfelmus
David Menendez wrote:
 I think replacing put s with put $! s should guarantee that the
 state is evaluated.
 
 If you're using get and put in many place in the code, you could try
 something along these lines:
 
 newtype SStateT s m a = S { unS :: StateT s m a } deriving (Monad, etc.)
 
 instance (Monad m) = MonadState s (SStateT s m) where
 get = S get
 put s = S (put $! s)
 

Interestingly, this is different from  Control.Monad.State.Strict . The
latter never forces the state itself, just the pair constructor of the
(result,state) pair.

Here the different cases:

evalLazy   m = Control.Monad.State.Lazy.evalState m 0
evalStrict m = Control.Monad.State.Strict.evalState m 0


-- Pair constructor non-bottom
GHCi evalLazy   $ put undefined
()
GHCi evalStrict $ put undefined
()

-- Pair constructor bottom
GHCi evalLazy   $ put $! undefined
*** Exception: Prelude.undefined
GHCi evalStrict $ put $! undefined
*** Exception: Prelude.undefined

-- Last pair constructor non-bottom
GHCi evalLazy   $ (put $! undefined)  put 1
()
-- Everything bottom
GHCi evalStrict $ (put $! undefined)  put 1
*** Exception: Prelude.undefined



Regards,
apfelmus

--
http://apfelmus.nfshost.com

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


Re: [Haskell-cafe] Re: Long running Haskell program

2009-11-12 Thread Matthew Pocock
2009/11/12 Heinrich Apfelmus apfel...@quantentunnel.de

 Interestingly, this is different from  Control.Monad.State.Strict . The
 latter never forces the state itself, just the pair constructor of the
 (result,state) pair.


 Yes. This bit me the first time I came across it. I think we need a
Control.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: Long running Haskell program

2009-11-12 Thread Matthew Pocock
2009/11/12 Heinrich Apfelmus apfel...@quantentunnel.de

 Interestingly, this is different from  Control.Monad.State.Strict . The
 latter never forces the state itself, just the pair constructor of the
 (result,state) pair.


Yes. This bit me the first time I came across it. I think we need a
Control.Monad.State.StrictOnState with strict behaviour on the state value.
I notice this same underlying issue is coming up in more than one thread on
these lists.

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


Re: [Haskell-cafe] Re: Long running Haskell program

2009-11-12 Thread Felipe Lessa
On Thu, Nov 12, 2009 at 8:01 AM, Matthew Pocock
matthew.poc...@ncl.ac.uk wrote:
 Yes. This bit me the first time I came across it. I think we need a
 Control.Monad.State.StrictOnState with strict behaviour on the state value.
 I notice this same underlying issue is coming up in more than one thread on
 these lists.

This monad would indeed be useful, however it may be confusing as
well.  For example, if you are inserting elements in a Map using a
lazy insert, seq'ing the map will only reduce it to WHNF (of course)
and move the insertion down one level in the tree.  IOW, I'd guess
that OP's problem can't be solved just by seq'ing the map, he would
have to use strict operations.  There's a strict insertWith in
Data.Map, but IIRC it's strict only on its combining operation, not on
the insertion itself.

Hmmm... maybe Control.Monad.State.RnfOnState? =P

Cheers,

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


Re: [Haskell-cafe] Re: Long running Haskell program

2009-11-12 Thread Matthew Pocock
How about:

instance (Monad m) = MonadState s (SStateT s m) where
get = S get
put s = S (put $ using s $ strategy m)

where our state monad has a strategy field?

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


[Haskell-cafe] Re: Long running Haskell program

2009-11-11 Thread Andy Stewart
David Leimbach leim...@gmail.com writes:

 As some of you may know, I've been writing commercial Haskell code for a 
 little bit here (about a
 year and a half) and I've just recently had to write some
 code that was going to run have to run for a really long time before being 
 restarted, possibly
 months or years if all other parts of the system cooperate as
 it's part of a server infrastructure management system.

 I recently ran into some serious space leak difficulties that would 
 ultimately cause this program to
 crash some time after startup (my simulator is also
 written in Haskell, and runs a LOT faster than the real application ever 
 could, this has enabled me
 to fast forward a bit the data growth issues and crash
 in minutes instead of days!)  

 Anyway, rather than try to paste it all here with images and such I thought 
 I'd stick it up on my
 blog so others could maybe benefit from the anecdote.
  It's difficult to disclose enough useful information as it is commercial 
 code not under an open
 source license, but there's neat diagrams and stuff there
 so hopefully the colors are at least amusing :-)

 http://leimy9.blogspot.com/2009/11/long-running-haskell-applications.html
Can you copy you blog at here?
http://leimy9.blogspot.com/2009/11/long-running-haskell-applications.html
is filter by GFW (http://en.wikipedia.org/wiki/Golden_Shield_Project) i
can't see it.

About crash free program, you can consider multi-process design, keep
Simple and Stable core running in RootProcess, and Core module won't
crash, and make unstable module running in ChildProcess, if you occur
some un-catch exception from ChildProcess, just reboot those sub-module.

I'm research some Haskell/Gtk+ program, sometimes
un-catch exception is unavoidable, multi-process is good chose to avoid
some exception crash all program.

Cheers,

  -- Andy

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


Re: [Haskell-cafe] Re: Long running Haskell program

2009-11-11 Thread David Leimbach
On Wed, Nov 11, 2009 at 8:20 AM, Andy Stewart lazycat.mana...@gmail.comwrote:

 David Leimbach leim...@gmail.com writes:

  As some of you may know, I've been writing commercial Haskell code for a
 little bit here (about a
  year and a half) and I've just recently had to write some
  code that was going to run have to run for a really long time before
 being restarted, possibly
  months or years if all other parts of the system cooperate as
  it's part of a server infrastructure management system.
 
  I recently ran into some serious space leak difficulties that would
 ultimately cause this program to
  crash some time after startup (my simulator is also
  written in Haskell, and runs a LOT faster than the real application ever
 could, this has enabled me
  to fast forward a bit the data growth issues and crash
  in minutes instead of days!)
 
  Anyway, rather than try to paste it all here with images and such I
 thought I'd stick it up on my
  blog so others could maybe benefit from the anecdote.
   It's difficult to disclose enough useful information as it is commercial
 code not under an open
  source license, but there's neat diagrams and stuff there
  so hopefully the colors are at least amusing :-)
 
 
 http://leimy9.blogspot.com/2009/11/long-running-haskell-applications.html
 Can you copy you blog at here?
 http://leimy9.blogspot.com/2009/11/long-running-haskell-applications.html
 is filter by GFW (http://en.wikipedia.org/wiki/Golden_Shield_Project) i
 can't see it.

 About crash free program, you can consider multi-process design, keep
 Simple and Stable core running in RootProcess, and Core module won't
 crash, and make unstable module running in ChildProcess, if you occur
 some un-catch exception from ChildProcess, just reboot those sub-module.


Believe it or not, this is a stack of Erlang - Haskell - C.

It works via pipes and is a concurrent system of management.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: Long running Haskell program

2009-11-11 Thread Wei Hu
I used to be a victim of GFW, so I can feel your pain. You may try to
subscribe to http://leimy9.blogspot.com/feeds/posts/default in your
Google Reader. In case that fails too, I've pasted the blog post
below, with no images:

I've been using Haskell in a serious way for about 2 years.  Been
using it in a professional sense about 1.5 years now in that, yes, I
am one of the lucky ones that gets to use Haskell at work.

The ride has been pretty smooth most of the time, as I've found that
the type system especially helps me to rule out certain classes of
bugs, easily test rather large chunks of programs as they're pure.
The interpreter allows experimentation and iteration of ideas that can
then be composed into the final compiled programs.  All of this gives
me a good deal of confidence that the code I'm writing is correct to
some degree up front, something I've come to expect from functional
programming languages over the years and greatly appreciate.

However I've felt compelled to comment that things aren't always so
smooth either.  I spent the better part of a weekend and a Monday
tracking down a space leak in a program that just was not allowed to
leak space.  I have a stack of a ReaderT StateT IO that I use to
communicate with a device through a passthrough program that speaks
CAN to a device for the purposes of creating a serial console
connection where there is only a CAN bus.  The Haskell program is
responsible for the management of the data found at the other end o
the serial connection and supports operations to the device through
the serial channel via a simple text protocol while forever polling
data on the serial endpoint.

What I had done was the equivalent of


pollerLoop :: Poller ()
pollerLoop = forever pollOnce



Where Poller is my monad stack.
pollOnce is  defined as,


pollOnce :: Poller ()
pollOnce  = do
checkCommandChannel -- see if there's a pending command to run
executePoll



Yes, this application is multi-threaded.  I have a logger thread, a
thread watching standard input of the program for queries and issuing
commands to the endpoint.  I have a thread per Poller, and the ability
to poll devices simultaneously.

The poller includes an implementation of my little expect syntax
which was based on a naive implementation of hGetChar and checking for
a desired result or timing out eventually.  The really data
inefficient version is a real screamer, beating the heck out of my
Parsec or even ReadP version, but because of the way I wrote it, with
a lot of reversing and prefix checking and substring slicing into
temporary areas, it's not useful for large input blocks over a long
time frame.

Still it's so fast that it's appropriate for certain sections of code.
 I measured and verified this via space profiling to see the real
runtime heap utilization (nice feature btw, I'd be dead without it
right now I think).

So what's the problem you're probably thinking?  Well it turns out
that since part of my state in StateT is a Data.Map, and that all my
polling and parsing of expect-passing blocks caused updates to a Map,
coupled with the language's default laziness caused a bit of a bomb
of PAP (Partial APplications of functions).

I had an ill-timed, project wise, discovery of a space leak.

I tried sprinkling $! and seq all over the place, rewriting big chunks
of code that used Text.Regex.Posix, to use Parsec and only got
incremental improvements.  The growth problem still existed, and would
eventually exhaust memory.  This was a real problem as this was an
application that was not supposed to stop when the other conditions of
the management system were ok.  It could run for months or even years!

I went through a whirlwind of emotions, and considered that perhaps I
should be working a different job.  Perhaps I could be a lion tamer?
It turned out what I thought was a lion was really an anteater
though... but that's literally a different story.

It turns out that by looping not inside the monad, but over the
execStateT/runReaderT expression I could pull all the state out, and
then re-inject it into another execStateT/runReaderT each poll, which
forced the strictness I needed on all state data, made the system
respond faster, and best of all, not crash

Diagrams below:

This first one is the before picture.  It shows the data growth by
cost center in my code.  As you can see things are getting worse
almost linearly as I poll.


This picture illustrates the result of pulling the state out of the
Monad, and re-injecting it, forcing it to be evaluated.  As you can
see, I've got much more manageable memory utilization.

This final one shows the new algorithm running with 2 threads, one
spawned a few seconds into the run.  You can see the initial burst of
the fast but inefficient expect algorithm, followed by a much more
regular memory utilization pattern.



I'd like to thank all the folks on #haskell on FreeNode who gave me
suggestions and hints to my vague problems regarding data growth and