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
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.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.
- New tips: Quirks of Scala Specialization
- Boxing, Specialization, Performance – recorded video and slides from talk by Iulian Dragos on the optimizations introduced in Scala 2.8
- Scala Performance Considerations – recorded video and slides from talk by Nermin Serifovic on performance pitfalls in Scala
- VisualVM – a profiling tool for the JVM (included in the latest Oracle Java JRE)