Posts

Parallel reduce: Hopac, Asyncs, Tasks and Scala's Futures

Image
Tuomas Hietanen posted a parallel reduce function that uses TPL Tasks. I found it interesting to compare performance of this function with analogues implemented using F# Asyncs, Hopac Jobs and Scala Futures. The author uses noop long-running reduce function to show that it's really run in parallel. In this blog post we are benchmarking another aspect of the implementations: how much extra cost is introduced by a particular parallezation mechanism (library) itself. We translate the original code almost as is to Tasks and Hopac: And Scala's Futures: The results (Core i5, 4 cores): Sequential List.reduce: Real: 00:00:00.014, CPU: 00:00:00.015, GC gen0: 0, gen1: 0, gen2: 0  Tasks: Real: 00:00:01.790, CPU: 00:00:05.678, GC gen0: 36, gen1: 10, gen2: 1  Hopac: Real: 00:00:00.514, CPU: 00:00:01.482, GC gen0: 27, gen1: 2, gen2: 1  Asyncs: Real: 00:00:37.872, CPU: 00:01:48.405, GC gen0: 90, gen1: 29, gen2: 4 Scala Futures: 4.8 seconds (Hopac - 3....

Fibonacci: Hopac vs Async vs TPL Tasks on .NET and Mono

Image
Hopac claims that its Jobs are much more lightweight that F# Asyncs. There are many benchmarks on Hopac github repository, but I wanted to make a simple and straightforward benchmark and what could be simpler that parallel Fibonacci algorithm? :) (actually there's a more comprehensive  benchmark in the Hopac repository itself, see Fibonacci.fs ) Sequential Fibonacci function is usually defined as So write a parallel version in Hopac where each step is performed in a Job and all these Jobs are (potentially) run in Parallel by Hopac's scheduler An equivalent parallel algorithm written using F# Asyncs ...and using TPL Tasks All three functions create *a lot* of parallel jobs/asyncs/tasks. For example, for calculating fib (34) they create ~14 million of jobs (this is why Fibonacci was chose for this test). To make them work efficiently we will use the sequential version of fib for small N, then switch to parallel version Now we can run both of the function with d...

D

I've to say, D is very interesting language with several unique features. What about performance? How it compares to VM-based languages? It took 3.6 seconds in debug mode and 1.3 seconds in release mode, which is on pair with F#. C# - 1.26 D (DMD) - 1.3 F# - 1.38 Nemerle - 1.45 Haskell - 2.8 Clojure - 9 Erlang - 17 Ruby - 60 Python - 120

Scala pros and cons from F# dev view

Recently I started to learn Scala (for about 2 weeks now). Here is prons and cons so far (note: I've not written any serious code yet, just have read "Scala for the impatient" and now reading "Programming in Scala" by Odersky): Prons Passing not evaluated block as argument ("by-name arguments". Allows to develop better DSLs) Macros! There are few libraries written with macros, impossible to implement in a language like c# or f# (MacWire etc.) Cons No not-nullable types (this is a huge one) Not whitespace sensitive (curly braces everywhere)  No type inference for arguments and, sometimes, for result type (signatures involving generic types may be really hairy)  No compiler warning on implicitly discarded expression value (possibly wrong code like arr.map(x => x * 2); arr.map(x => x * 3). The result of the first map is discarded silently. In contrast, F# forces us to write arr |> Array.map (fun x -> x * 2) |> ignore; arr...

STM revisited: add Scala

Some time ago I compared F# and Haskell STM implementation performance. Today I'm adding Scala into it: So, it's more than two times slower than Haskell, but more than 3 times faster than F#. Interesting.

Duck typing in Scala

Scala keeps surprising me. It has much good stuff that F# has. For example, I believed that statically resolved type parameters are unique to F#. Turns out this is not the case. Scala has equivalent feature called "structural types". It has nice syntax compared to F#'s statically resolved type parameters. However, it uses reflection under the hood while F# uses inlining to instantiate functions in-place at compile time. This approach should definitely have awful performance characteristics. Surprisingly, it's not the case: Static call took about 0.5 seconds, "duck typing" call took about 4 seconds. It only 8-10 times slower than static call. Frankly, I expected something like 100x - 1000x degradation. So, it's not as fast as the equivalent feature in F#, but it certainly practically useful in many circumstances.

STM: F# vs Haskell

STM is a very nice parallel programming model used intensively in Haskell and Clojure. There's a F# implementation which can be found in FSharpx library. Today I'm going to test performance of both the Haskell and the F# STMs. The test is very simple - read a couple TVars, check their equality, then write them back incremented by 1, repeat a million times. First, the Haskell code: So, it took about 170 ms. OK, now F#: It took about 1,6 seconds which is an order of magnitude slower than the Haskell result. It's rather frustrating.