Ich muss Millionen von X / Y-Doppelpaaren als Referenz in meinem Java-Programm speichern. Ich möchte den Speicherverbrauch sowie die Anzahl der Objektreferenzen so gering wie möglich halten. Nach einigem Nachdenken entschied ich mich, die beiden Punkte in einem winzigen Doppel-Array zu halten. Das ist vielleicht eine gute Idee, das Setup sieht so aus:
%Vor%Ich dachte, mit dem Array würde die Verbindung zwischen der Klasse und meinen X- und Y-Variablen in einer Klasse wie folgt verhindert:
%Vor%Nachdem ich jedoch gelesen habe, wie öffentliche Felder in Klassen gespeichert werden, dämmerte es mir, dass Felder möglicherweise nicht als zeigerartige Strukturen strukturiert sind, vielleicht speichert die JVM diese Werte einfach im zusammenhängenden Speicher und weiß, wie man sie ohne findet eine Adresse, die die Klassendarstellung meines Punktes kleiner macht als das Array.
Die Frage ist also, welche einen kleineren Speicherbedarf hat? Und warum?
Ich bin besonders daran interessiert, ob Klassenfelder einen Zeiger verwenden und daher einen 32-Bit-Overhead haben oder nicht.
Letzteres hat die kleinere Grundfläche.
Primitive Typen werden in der containing-Klasse inline gespeichert. Ihr Node
benötigt also einen Objektheader und zwei 64-Bit-Slots. Das Array, das Sie angeben, verwendet einen Array-Header (& gt; = eine Objektkopfzeile) und zwei 64-Bit-Slots.
Wenn Sie auf diese Weise 100 Variablen zuweisen, ist das nicht so wichtig, da nur die Headergrößen unterschiedlich sind.
Vorbehalt: All dies ist etwas spekulativ, da Sie die JVM nicht angegeben haben - einige dieser Details können sich nach JVM unterscheiden.
Ich glaube nicht, dass Ihr größtes Problem darin besteht, die Daten zu speichern, ich denke, es wird abgerufen, indexiert und manipuliert.
Grundsätzlich ist jedoch ein Array der richtige Weg. Wenn Sie Zeiger speichern möchten, verwenden Sie ein eindimensionales Array. (Jemand hat das schon gesagt).
Zuerst muss festgestellt werden, dass die tatsächliche Speicherplatznutzung von der JVM abhängt, die Sie verwenden. Es ist streng umsetzungsspezifisch. Das Folgende ist für eine typische Mainstream-JVM.
Die Frage ist also, welche einen kleineren Speicherbedarf hat? Und warum?
Die 2. Version ist kleiner. Ein Array hat den Overhead des 32-Bit-Felds im Objektkopf, das die Länge des Arrays enthält. Im Fall eines Nicht-Array-Objekts ist die Größe implizit in der Klasse und muss nicht separat dargestellt werden.
Beachten Sie jedoch, dass dies ein festes über Kopf pro Array-Objekt ist. Je größer das Array ist, desto weniger wichtig ist der Aufwand in der Praxis. Und die Kehrseite der Verwendung einer Klasse anstelle eines Arrays ist, dass die Indizierung nicht funktioniert und der Code dadurch möglicherweise komplizierter (und langsamer) wird.
Ein Java 2D-Array ist eigentlich ein Array von 1D-Arrays (usw.), so dass Sie die gleiche Analyse auf Arrays mit höherer Dimensionalität anwenden können. Je größer die Größe eines Arrays in einer Dimension ist, desto weniger Auswirkungen hat der Overhead. Der Overhead in einem Array 2x10
ist kleiner als in einem Array 10x2
. (Denken Sie durch ... 1 Array der Länge 2 + 2 der Länge 10 gegen 1 Array der Länge 10 + 10 der Länge 2. Der Overhead ist proportional zur Anzahl der Arrays.)
Ich bin besonders daran interessiert, ob Klassenfelder einen Zeiger verwenden und daher einen 32-Bit-Overhead haben oder nicht.
(Sie sprechen tatsächlich über Instanzfelder, nicht über Klassenfelder. Diese Felder sind nicht static
...)
Felder, deren Typ ein primitiver Typ ist, werden direkt im Heap-Knoten des Objekts ohne Referenzen gespeichert. In diesem Fall gibt es keinen Zeiger-Overhead.
Wenn es sich bei den Feldtypen jedoch um Wrapper-Typen handelte (z. B. Double
anstatt double
), könnte der Overhead einer Referenz UND der Overhead des Objektheaders für das Objekt Double
vorhanden sein.