Skip to content

Scala – Best Practices – Performance

So we should preserve it. I don’t think that digital storage is necessarily a good thing, but I definitely think that digital manipulation is interesting.

-Sean Booth

This Scala best practice is inspired from Databricks Scala Guide. Most of day to day programming best practices are covered in this Scala best practice guide. I will keep updating this space from time to time. Happy coding.


  1. Performance

Performance

For the vast majority of the code you write, performance should not be a concern. However, for performance sensitive code, here are some tips:

Microbenchmarks

It is ridiculously hard to write a good microbenchmark because the Scala compiler and the JVM JIT compiler do a lot of magic to the code. More often than not, your microbenchmark code is not measuring the thing you want to measure.

Use jmh if you are writing microbenchmark code. Make sure you read through all the sample microbenchmarks so you understand the effect of deadcode elimination, constant folding, and loop unrolling on microbenchmarks.

Traversal and zipWithIndex

Use while loops instead of for loops or functional transformations (e.g. mapforeach). For loops and functional transformations are very slow (due to virtual function calls and boxing).

val arr = // array of ints
// zero out even positions
val newArr = list.zipWithIndex.map { case (elem, i) =>
  if (i % 2 == 0) 0 else elem
}

// This is a high performance version of the above
val newArr = new Array[Int](arr.length)
var i = 0
val len = newArr.length
while (i < len) {
  newArr(i) = if (i % 2 == 0) 0 else arr(i)
  i += 1
}

Option and null

For performance sensitive code, prefer null over Option, in order to avoid virtual method calls and boxing. Label the nullable fields clearly with Nullable.

class Foo {
  @javax.annotation.Nullable
  private[this] var nullableField: Bar = _
}

Scala Collection Library

For performance sensitive code, prefer Java collection library over Scala ones, since the Scala collection library often is slower than Java’s.

private[this]

For performance sensitive code, prefer private[this] over privateprivate[this] generates a field, rather than creating an accessor method. In our experience, the JVM JIT compiler cannot always inline private field accessor methods, and thus it is safer to use private[this] to ensure no virtual method call for accessing a field.

class MyClass {
  private val field1 = ...
  private[this] val field2 = ...

  def perfSensitiveMethod(): Unit = {
    var i = 0
    while (i < 1000000) {
      field1  // This might invoke a virtual method call
      field2  // This is just a field access
      i += 1
    }
  }
}
Published inScalaTechnical Posts