I have a class that must work with Double and Float. I use generic with @specialized
annotation for (Double, Float)
due to performance requirements. There are two third-party functions, that I need to call. ffunc(x: Float)
accepts Float
, dfunc(y: Double)
accepts Double
. At some point I have to call either ffunc
or dfunc
. I use scala pattern matching for that purpose. My code looks as follows:
class BoxingTest[@specialized(Double, Float) T] {
def foo(p: T): Unit = {
p match {
case dp: Double => dfunc(dp)
case df: Float => ffunc(df)
}
}
}
However, scala compiler provides non-optimized bytecode for specialized versions. When I look inside the bytecode of specialized class, I see the non optimized matching code that converts my specialized type to object. There are also additional boxing/unboxing as follows:
41: invokestatic #21 // Method scala/runtime/BoxesRunTime.boxToDouble:(D)Ljava/lang/Double;
44: invokestatic #39 // Method scala/runtime/BoxesRunTime.unboxToDouble:(Ljava/lang/Object;)D
Could you suggest a replacement of matching code with the code that will be optimized and will avoid boxing/unboxing?
This came up previously. I think the best bet was to override the specialized method:
scala> class X[@specialized(Int, Double) A] { def f(a: A): String = ??? }
defined class X
scala> trait T { def f$mcI$sp(i: Int): String = "my int" }
defined trait T
scala> val x = new X[Int] with T
x: X[Int] with T = $anon$1@6137cf6e
scala> x.f(42)
res0: String = my int
That was probably on SO.