2012-12-10 4 views
5

konvertieren würde ich gerne wissen, wie (wenn es möglich ist) könnte ich eine Java-Klasse programmieren, um einen Datenlayout Array of Class, zum Beispiel mit:Wie automatisch von Array der Klassen Klasse von Arrays

public class X{ 

    double a; 
    double b; 
    double c; 
} 

public X array_of_x[SIZE] = new X [SIZE]; 

aber

public class X{ 

    double a[] = new double [SIZE]; 
    double b[] = new double [SIZE]; 
    double c[] = new double [SIZE]; 
} 

public X class_x = new X(); 

Mein Ziel ist es, dass der Programmierer in einer intuitiven Art wie die erste programmierter könnte, aber interne ich würde Transformationen tun so könnten die Daten sein: intern würden die Datenspeicher als Layout Class of Arrays so sein kontinuierlich in der Erinnerung, und ich würde Mehr Leistung erreichen.

Gibt es eine Möglichkeit, dies zu tun, so dass es jede Klasse mit dem ersten Typ von Struktur akzeptieren und in der Lage sein würde, es in den zweiten Ansatz zu konvertieren? (oder ist ein Werkzeug, das diese Art von Transformation durchführen kann).

+1

Ich mache das viel, aber immer mit der Hand. Es wäre interessant zu hören, was die anderen sagen. (+1) – NPE

+4

Es gibt keine Möglichkeit, dies zu tun, aber warum, glauben Sie, wird es in einem Maße schneller sein, das sich auf die Leistung auswirkt? –

+1

@MiserableVariable: Bessere Lokalität der Referenz und kompaktere Darstellung. Ich habe diese Art von Zeug ziemlich viel profiliert, und in vielen Fällen gibt es keinen Wettbewerb. – NPE

Antwort

3

Lassen Sie uns eine Schnittstelle erstellen, die das erste Layout zur Verwendung zeigt, und eine Implementierung für diese Schnittstelle, die intern das zweite Layout verwendet. (Access-Modifikatoren aus dem Code gestrippt.)

interface X { 
    double getA(); 
    double getB(); 
    double getC(); 
}; 

interface ArrayOfX { 
    X get(int index); 
}; 

class ContiguousArrayOfX implements ArrayOfX { 
    class ContiguousX implements X { 
     int index; 
     ContiguousX(int index) { 
      this.index = index; } 
     double getA() { return a[index]; } 
     double getB() { return b[index]; } 
     double getC() { return c[index]; } 
    } 

    X get(int index) { 
     return new ContiguousX(index); } 

    double a[] = new double [SIZE]; 
    double b[] = new double [SIZE]; 
    double c[] = new double [SIZE]; 
}; 

Wenn Sie die Belastung für den GC verringern möchten, können Sie auch alle Instanzen ContiguousX zwischenzuspeichern. Es hängt ziemlich stark von der Eignung des JIT-Compilers ab, ob die ContiguousX Objekte auf dem Heap überhaupt zugewiesen werden - sie könnten gut im Stack leben, in diesem Fall ist der Overhead vernachlässigbar.

interface FasterArrayOfX { 
    double getA(int index); 
    double getB(int index); 
    double getC(int index); 
}; 

class FasterContiguousArrayOfX extends ContiguousArrayOfX implements FasterArrayOfX { 
    // Exercise left to the reader 
}; 

Durch die Programmierung gegen eine Schnittstelle, die Sie immer frei sind, um die Lagerung später wählen: Als letzten Ausweg, können Sie eine alternative Schnittstelle für den schnellen Zugriff definieren.

Es ist ziemlich einfach, einen Code-Generator für ein bestimmtes Klassenlayout zu schreiben. Der obige Code kann als Textbaustein verwendet werden, nur die Methoden- und Array-Deklarationen hängen vom Klassenlayout ab, das Sie erhalten möchten. Mir ist kein existierendes Werkzeug bekannt.

+0

Das sieht gut aus, ich habe AspectJ verwendet, um die gets und setzt abfangen und ersetzen ihre Ausführung für andere erhält und setzt, die auf das Array zugreifen, aber Ihr Weg sieht sauberer. – dreamcrash

+0

@dreamcrash: Möchten Sie Ihre Implementierung teilen? – krlmlr

+0

Ich möchte zeigen, aber es ist nicht mein Eigentum, Sie wissen, Vertragsprobleme – dreamcrash