A Google search for real-time haskell yields little of interest, which I suppose isn’t too surprising. Haskell, if you’re not familiar, is not just a pure functional language, but a lazy one. On the surface, this makes it a dreadfully poor choice for a couple of reasons.
- Haskell code tends to be slow. I’ve started using the Gentoo language shootout as my baseline for language comparisons—it seems fairly unbiased if nothing else—and with a few exceptions, Haskell just doesn’t stack up well. This isn’t too surprising: laziness adds overhead. My mentioning performance might get the hardcore real-timers in a tiff—theoretically performance has nothing to do with real-time—but in the real world, real-time is typically either done in embedded situations where hardware resources are scarce, or else we’re in a soft real-time situation playing pr0n, and speed is important.
- Haskell code is unpredictable. This is the biggest flaw in Haskell that Simon Peyton-Jones has offered (that I’m aware of). When tracing through Java code, it’s trivial to derive complexity, and even a rough gauge on absolute running time, just by glancing at the code. Laziness takes this all away. I’ll talk about this in a later post perhaps.
- Haskell is garbage collected.
It’s that last point I want to talk about. Garbage collection is typically not used in real-time systems, particularly hard real-time systems, for good reason. Imagine writing the quintessential real-time example code—nuclear power plant code; yes, I can dream—and you’ve reserved your time slice, grabbed your mutex, and then the garbage collector decides to run for 400ms. Not cool.
For my CS 888 project, I think I’m going to propose changing Haskell’s garbage collector to provide a real-time interface. Something along the lines of:
gcNextCollectionUpperBound :: IO Int
gcBound :: Int -> IO a -> IO a
The first function would give an upper bound on how long the next round of garbage collection would take (in milliseconds). The second function/combinator would execute a section of code, guaranteeing a bound on the amount of time garbage collection will take, such as:
do gcTime <- gcNextCollectionUpperBound
return $ gcBound (gcTime + 200) do
requestTimeSlice (gcTime + 200)
mutex <- getMutex
doComputation
saveLives
giveUpMutex mutex
return answer
This way we’re guaranteed that we complete saveLives before the garbage collector eats up all our time. So that’s about all I need for the interface; all I need now is the implementation. Yay, I’m half done!
GHC’s documentation on its garbage collector is a big weak, so I’ll have to dig into the source. My understanding through a bit of reading is that right now GHC uses a hybrid system, with almost all programs using the copy collector exclusively, and the other part of the system being a generational collector. This is somewhat exciting because I haven’t found any papers yet discussing real-time copy collector systems yet.
We’ll see how far I get in this. The nice thing about a project like this is that a naïve implementation can be done hopefully without too much work (do garbage collecting until you run out of time, then just give up). Even coming up with a naïve upper bound is easy (return INT_MAX). But the project offers itself to putting effort into a more finessed solution, too.
I don’t know, we’ll see what Watt says about it.
February 17, 2007 at 10:32 am
For real-time it doesn’t really matter if a language implementation is slow as long as it’s fast enough. It’s predictability that is important. But if you are doing soft real-time, even a little unpredictable is fine. Erlang uses GC and is not totally predictable, but it’s main application area is (used to be) soft real-time systems.
(BTW, I’d not say complexity is trivial for any language. Maybe for code without loops.)
February 17, 2007 at 10:34 am
> with a few exceptions, Haskell just doesn’t stack up well.
Once we fixed the programs that broke on the upgrade to ghc 6.6, the results actually look pretty good for GHC. Particularly if you compare it against comparable high level languages.
http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=all
February 17, 2007 at 10:17 pm
Before deciding that garbage collection can’t possibly give any kind of real-time guarantees, see the Metronome and related work. I’ve forgotten the details about concurrent garbage collection with GHC–has do to with how thunks double as read barriers–but the general idea should work. The other catch is that the implementation is for Java. The ACM Queue paper has some interesting performance measurements, including a CPU load graph.
http://citeseer.ist.psu.edu/bacon03realtime.html
http://www.acmqueue.org/modules.php?name=Content&pa=showpage&pid=454
http://domino.research.ibm.com/comm/research_projects.nsf/pages/metronome.metronomegc.html
February 25, 2007 at 5:00 pm
dons wrote “Particularly if you compare it against comparable high level languages.”
Shame on you Don! That webpage talks about April Fool’s Day and boldly states “For every complex problem, there is a solution that is simple, neat, and wrong.”
http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=ghc&lang2=clean
http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=ghc&lang2=gcc
February 25, 2007 at 6:27 pm
Yes I’m looking at Metronome. I should say this is just a course project, so it’s nothing terribly novel. I know people have looked at real-time garbage collection before, but sadly this sort of stuff doesn’t make it into too many implementations.
February 27, 2007 at 10:52 am
[…] my CS888 project Posted by Mike under CS 888 , Garbage collection , Haskell I’ve mentioned before my CS888 project, which is taking GHC’s garbage collector and adding real-time hooks into it. There will be […]
March 5, 2007 at 4:32 am
I am already using haskell in the design/prototype of a large real-time control system – and if history is anything to go by the prototype in haskell will be the production thing.
The predictability I need is “rate equivalence” – its about doing the right number of events/steps over a long(ish) period with a bound on the “jitter” of each event.
Does it need to be as complex as you suggest – could you not just say “run GC for max millisec (+jitter)” as an interface with some other inquiry functions to get hints?
Why do you need such a complex interaction with the scheduler?
If you want to chat – get in touch.
March 5, 2007 at 10:56 am
It sounds like that’s sort of the interface I’m providing. I have one (not really necessary) function to get an estimate on the amount of time GC might time, and then another function to give a hard bound on how much time the GC is allowed to take. The idea of a jitter is an interesting one, sort of providing a soft bound and a hard bound. I’ll think about that.
And if you have any information on your project, I’d love to take a look at it. My email address is mburrel@uwo.ca.
March 9, 2007 at 5:35 pm
There was a paper on real-time garbage collection in Haskell, you may want to take a look at it: http://research.microsoft.com/~simonpj/Papers/inc-gc.htm
March 9, 2007 at 6:45 pm
Oh excellent. Thank you very much! I don’t know why I hadn’t found this prior.
February 18, 2009 at 2:54 pm
Search for Mentronom garbage collector for Java. It is for real time usage.
April 15, 2009 at 6:45 am
My friend on Facebook shared this link and I’m not dissapointed at all that I came here.
August 23, 2013 at 8:42 pm
Thanks a lot for sharing this with all folks you actually recognise what you’re speaking about! Bookmarked. Please additionally discuss with my website =). We could have a link change contract between us