Вопрос

For performance and safety I would like to implement a fixed-size vector which is both immutable and specialized (I need fast arithmetics). My first idea was to use the @specialized annotation (because I need both integers and reals).

Here is a first try:

package so
class Vec[@specialized A] private[so] ( ary: Array[A] ) {
  def apply( i: Int ) = ary(i)
}

However, when I analyze the resulting bytecode with javap, I can see that the elements are still boxed. For instance:

public double apply$mcD$sp(int);
  Code:
   0:   aload_0
   1:   iload_1
   2:   invokevirtual   #33; //Method apply:(I)Ljava/lang/Object;
   5:   invokestatic    #83; //Method scala/runtime/BoxesRunTime.unboxToDouble:(Ljava/lang/Object;)D
   8:   dreturn

It looks like arrays are not specialized which seems silly, because arrays are specialized on the JVM.

Is there something I can still do to reach my goal ?

Это было полезно?

Решение

You are likely looking at the code compiled to Vec.class. According to this thread the specialization occurs in subclasses. This can be verified in the REPL:

scala> class Vec[@specialized A] ( ary: Array[A] ) {
     |   def apply( i: Int ) = ary(i)
     | }
defined class Vec

scala> new Vec( Array[Int](1) ).getClass
res0: java.lang.Class[_ <: Vec[Int]] = class Vec$mcI$sp

As you can see for Int it is using the subclass Vec$mcI$sp. And if you run javap on that class you will see that it is infact specializing the code properly. This is what the apply method looks like in Vec$mcI$sp.class using javap:

  public int apply(int);
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0       
         1: iload_1       
         2: invokevirtual #13                 // Method apply$mcI$sp:(I)I
         5: ireturn       

Which I suppose is what you want when using Int.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top