Profiling performance in Scala

Boxing and unboxing of primitive types

Using primitive types in parameterized generic classes can lead to some performance degradation in Scala. Type parameters in generic classes cannot be resolved as primitive types and instead becomes Object references. This mean primitive types like Int or Float in type parameters must be converted to and from an Object for each method invocation involving these type parameters. This boxing and unboxing can be optimized away using the @specialized annotation introduced in Scala 2.8. Some additional classes and methods for handling primitive types will as a result get added for each specialized generic class.

class Data[@specialized T](x: Int, y: Int, value: T)

To get the benefits of @specialized you need to annotate type parameters in your generic classes. If you are unsure where unboxing and boxing leads to the biggest performance hits, you need to profile your application with a tool like VisualVM, which is freely available and is fairly easy to get started with. It runs in it’s own JVM and let you connect to and profile other running JVMs.

During profiling you need to look for invocation of methods from scala.runtime.BoxesRunTime. These will be listed as BoxesRunTime.boxToInt and BoxesRunTime.unboxToInt etc. for each primitive type. A high number of invocations of these methods means your generic classes can be optimized for boxing and unboxing. To find the stacktraces that resulted in these calls, you must create snapshots from the running profiler. In these snapshots you can trace where the boxing and unboxing originated from.

For more information about the @specialized annotation see this talk by Iulian Dragos who was responsible for its implementation in Scala.

References

Leave a Reply

Your email address will not be published. Required fields are marked *