2012-04-21 14 views
12

Dla wydajności i bezpieczeństwa chciałbym zaimplementować wektor o stałym rozmiarze, który jest niezmienny i wyspecjalizowany (potrzebuję szybkiej arytmetyki). Moim pierwszym pomysłem było użycie adnotacji @specialized (ponieważ potrzebuję zarówno liczb całkowitych, jak i liczb rzeczywistych).Implementacja stałego rozmiaru, niezmiennego i wyspecjalizowanego wektora

Oto pierwsza próba:

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

Jednak, kiedy analiza uzyskanego kodu bajtowego z javap, widzę, że elementy są nadal zapakowane. Na przykład:

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 

Wygląda tablice nie są wyspecjalizowane, które wydaje się głupie, ponieważ tablice są wyspecjalizowane na JVM.

Czy jest coś, co mogę jeszcze zrobić, aby osiągnąć mój cel?

+0

Jaką wersję używasz? Dla mnie wygląda dobrze z 2.9.2. –

+0

Próbowałem z wersjami 2.9.2 i 2.8.2. – paradigmatic

Odpowiedz

9

Prawdopodobnie patrzysz na kod skompilowany do Vec.class. Według this thread specjalizacja występuje w podklasach. Można to sprawdzić w 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 

Jak widać na Int to jest przy użyciu podklasy Vec$mcI$sp. A jeśli uruchomisz javap na tej klasie, zobaczysz, że to rzeczywiście działa poprawnie. To właśnie zastosowanie metoda wygląda w Vec$mcI$sp.class użyciu 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  

Które Przypuszczam, co chcesz podczas korzystania Int.