Don't forget to also checkout my second blog containing articles to all other related ICT topics!!

Friday, May 25, 2012

Importance of immutability for concurrency

Let's take a look at how much performance we may gain when applying immutability to our code. I will let the code snippets speak for themselves. Below a generic trait with 3 methods of which two are important: the find and save method.
```package robbypelssers.concurrency

trait Store[K,V] {
def find(k: K): Option[V]
def save(v: V): Unit
def getName(): String
}
```

Now we create a mutable and immutable store (both insert key-value pairs (index mapped to fibonacci number) in respectively a mutable and immutable hashmap.
```package robbypelssers.concurrency

import collection.mutable.HashMap

class MutableFibonacciStore extends Store[Int, Int] with Fibonacci {

val store = new HashMap[Int, Int]

def find(n: Int): Option[Int] = synchronized(store.get(n))

def save(n: Int): Unit = synchronized(store.put(n, fibonacci(n)))

def getName() = "MutableFibonacciStore"

}
```

```package robbypelssers.concurrency

import collection.immutable.HashMap

class ImmutableFibonacciStore extends Store[Int, Int] with Fibonacci {

var store = new HashMap[Int,Int]

def find(n: Int): Option[Int] = store.get(n)

def save(n: Int): Unit = synchronized(store = store + ((n, fibonacci(n))))

def getName() = "ImmutableFibonacciStore"

}
```

```package robbypelssers.concurrency

trait Fibonacci {

def fibonacci(n: Int): Int = n match {
case 0 => 0
case 1 => 1
case _ => fibonacci(n-2) + fibonacci(n-1)
}

}
```

Below a very simple profiler which will give some idea of how long both stores will take to do a lot of calls to find and save.
```package robbypelssers.concurrency

import java.util.Date

object Profiler {

/**
* profile method works like an Around Advice in AspectOriented programming
*/
def profile[T](body: => T) = {
val start = new Date()
val result = body
val end = new Date()
println("Execution took " + (end.getTime() - start.getTime()) / 1000 + " seconds")
result
}

}
```

```package robbypelssers.concurrency

import java.util.Date
import Profiler._
object StoreConcurrencyTest extends App {

val immutableStore = new ImmutableFibonacciStore()
val mutableStore = new MutableFibonacciStore()
val numberOfOperations = 40

def useStore(store: Store[Int,Int], n: Int) {
println("using " + store.getName())
for (x:Int <- 1 to n) {
store.save(x)
}
for (x:Int <- 1 to n) {
store.find(x)
}
}

profile(useStore(immutableStore, numberOfOperations))
profile(useStore(mutableStore, numberOfOperations))

}
```

```using ImmutableFibonacciStore
Execution took 1 seconds
using MutableFibonacciStore
Execution took 4 seconds
```