Scala – Performance Optimization

First, we talked lot of information about performance optimization, including slick’s performance optimization by connection pool, JavaScript High Performance tips, MySQL’s performance tuning, and Play Framework Tuning(1) and Tuning(2). If we think it is enough, we are too naive. This post I will list performance optimization tips on Scala.

  1. par
    If we have N tasks which don’t have any relationship between each task, like order, shared variable, we can consider using the parallel collection to fasten computation.
    The parallel collection will make use of max-currency depending on the number of cores to execute which will greatly improve function’s efficiency.

    val list = List[String]("a", "b", "c", ...)
    list.par.foreach( r => {
      ... // your task.  

    Sometimes, the sequential implementation might have better performance than parallel implementation. That’s because using parallel collection has some overhead for distributing(fork) and gathering(join) the data between cores. Thus one can conclude having heavy computations, parallel collections can be of great performance improvement.

  2. Future
    Future is the same with par which can reach to the same purpose.

    import scala.concurrent.{Await, Future}
    import scala.concurrent.duration._
    val arr = List[String]("a", "b", "c")
    val futures = r => Future {
      ... // your task.
    val future = Future.sequence(futures)
    Await.result(future, 1 hour)
  3. Avoid unnecessary loop
    Even though we have  the parallel method to fasten steps, avoiding unnecessary loop is still needed. For my code, I use the random method to handle tokens selection problem to make sure the resources are fair to every customer. This is benefit from the probability theory.
  4. print out thread name to debug parallel running status
  5. Separate ExectureContent
    If you don’t want to influence default ExectureContent, you can create additional one to separate it.

    implicit val ec = ExecutionContext.fromExecutor(Executors.newCachedThreadPool())

    newCachedThreadPool vs newFixedThreadPool
    Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. At any point, at most nThreads threads will be active processing tasks. If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available. If any thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks. The threads in the pool will exist until its is explicitly shutdown.
    Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks. Calls to execute will reuse previously constructed threads if available. If no existing thread is available, a new thread will be created and added to the pool. Threads that have not been used for sixty seconds are terminated and removed from the cache. Thus, a pool that remains idle for long enough will not consume any resources. Note that pools with similar properties but different details (for example, timeout parameters) may be created using ThreadPoolExecutor constructors.
    If you have a huge number of long running tasks I would suggest the FixedThreadPool. Otherwise, please choose CachedThreadPool.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s