Подтвердить что ты не робот

Внедрение фиксированного, неизменяемого и специализированного вектора

Для производительности и безопасности я хотел бы реализовать вектор фиксированного размера, который является неизменным и специализированным (мне нужна быстрая арифметика). Моя первая идея заключалась в использовании аннотации @specialized (потому что мне нужны как целые числа, так и числа).

Вот первая попытка:

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

Однако, когда я анализирую полученный байт-код с помощью javap, я вижу, что элементы по-прежнему в коробке. Например:

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

Похоже, что массивы не специализируются, что кажется глупым, потому что массивы специализируются на JVM.

Есть ли что-то, что я могу сделать для достижения своей цели?

4b9b3361

Ответ 1

Вероятно, вы просматриваете код, скомпилированный в Vec.class. Согласно этой теме специализация происходит в подклассах. Это можно проверить в 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

Как вы можете видеть для Int, он использует подкласс Vec$mcI$sp. И если вы запустите javap в этом классе, вы увидите, что это инфанкт, специализирующийся на коде. Вот как выглядит метод apply в Vec$mcI$sp.class с помощью 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       

Я полагаю, это то, что вы хотите при использовании Int.