6 ms·
Recently I benchmarked a small network server written in Haskell. During the load testing the GHC runtime would allocate at rates of 1.6GB/s which is highly unu
by zimbatm 12y ago
Recently I benchmarked a small network server written in Haskell. During the load testing the GHC runtime would allocate at rates of 1.6GB/s which is highly unusual from my experience but is apparently normal for pure functional languages. The impressive bit is that during the operations the heap was never bigger than 50MB and GC pauses longer than 100ms.
If we where to re-write all our ruby code to be purely functional I don't think that CRuby GC would keep up very long with that kind of memory pressure.
- imanaccount247 12y ago>but is apparently normal for pure functional languages Where did you hear that? >and GC pauses longer than 100ms. Yikes! That is not normal at all. You wouldn't be able to write a decent webserver in haskell if that were normal.
- samnardoni 12y agoI think he/she meant the GC pauses were never longer than 100ms.
- imanaccount247 12y agoYes, and getting anywhere close to 100ms is not normal at all. Warp benchmarks show total request latency never goes above 50ms or so, a 100ms gc pause would be very apparent.
- zimbatm 12y agoIt's from memory, it's possible that the major GC where around 50ms. Minor GC where around 5ms for sure.
- zimbatm 12y ago> but is apparently normal for pure functional languages Where did you hear that? It's certainly true for Clojure as well. My guess is that it applies to any language that uses immutable data structures. I remember Rich Hickey talking about issues with the JVM due to clojure's unusual allocation model in one of his talks.
- imanaccount247 12y agoIt may well be true for clojure, but it is not for haskell. I know both clojure and scala have issues due to assumptions in the JVM execution model that don't play well with functional programming, but ghc was written explicitly just for haskell.
- codygman 12y agoSmall network server? Was it a custom one or one you got from somewhere? I know for a fact that wai, warp, and snap-server are way faster than that.
- zimbatm 12y agoA custom non-HTTP TCP server with STM and forkIO
- merijnv 12y agoThe reason GHC allocates at such an aggressive rate is the fact that memory allocation is really cheap in GHC. Allocating memory on the GHC heap is literally just bumping the "top of heap ptr", so writing one word. The idea is that 90% of allocations are very short-lived, so allocating a ton doesn't matter as long as you can throw it away cheaply. Suppose we have an inner loop over an array, summing values. We may allocate at 1.6 GB/s doing the computation, but everything except the last value is garbage. When we GC we simply copy this last value from the current heap and reset the "top of heap pointer". Yet another cheap operation. There's a lot more going on (generational GC, nursery's and what not), but GHC's GC heavily abuse some facts that, for example, CRuby cannot, such as the fact that older generations can never reference data in newer generations, so GCing the current generation never has to perform "major GC" (i.e. checking the older data whether it still needs the current generation).
- theflubba 12y agoBecause, you failed to properly set up GHC, you don't have the right to say anything about Haskell or functional programming.
- zimbatm 12y agoIt's the Internet, why wouldn't I write about my experience ? And I'm sure it's possible to tune GHC. The argument is that if you're going to write immutable data structures in ruby then there is going to be more GC pressure. I don't think it's possible to optimise the ruby GC anywhere near the GHC one because of the mutable nature of the language.