2012-10-25 3 views
8

Java virtuelle Maschinen können auch int -breite für short Felder verwenden (dies hängt von ihrer internen Implementierung ab). Nur die Arrays (short[]) sind eine Ausnahme, bei der immer gewährleistet ist, dass sie intern auch weniger Platz benötigen als ein int[]). Was ist mit Dalvik?Speicherbedarf für "kurze" Felder in Dalvik?

z. Ich habe eine Klasse, die 50 Felder vom Typ short enthält. In meiner Anwendung existieren manchmal 10000 dieser Klassen. Dies bedeutet, dass die short Felder 1 MB Speicher verwenden sollten, aber wenn Dalvik 4 Bytes für short Werte intern verwendet, dann wird dies 2MB Speicherauslastung sein.

Wie viel Speicher sollte ich von Dalvik erwarten? (Dies bezieht sich auf die Verwendung des internen Speichers, und mir ist bewusst, dass dies möglicherweise nicht durch die Systemspeicherauslastung widergespiegelt wird, z. B. weil Dalvik bereits eine größere Speichermenge vom System reserviert hat.)

+1

An den Benutzer, der eine (Formatierung) Bearbeitung für meinen Beitrag vorbereitet: Danke. Leider ließ mich das System nicht akzeptieren, es hieß "Bearbeitung wurde bereits abgelehnt". Soweit ich mich erinnern kann, habe ich versucht, Ihre Änderungen selbst vorzunehmen. –

+0

"Java Virtual Machines sind auch für die Verwendung von int-sized width für kurze Felder bekannt" Könnten Sie diese Aussage mit irgendeiner Referenz sichern? – kosa

+0

Ich war dort ein bisschen ungenau, also habe ich es bearbeitet. Hier sind einige verwandte stackoverflow Themen: http://stackoverflow.com/questions/8855754/android-does-short-take-really-2-bytes http://stackoverflow.com/questions/1904857/which-is-better- to-use-short-or-int –

Antwort

4

In Dalvik sind doppelte und lange Felder 8 Bytes, alles andere (einschließlich kurze) ist 4 Bytes.

Auf der anderen Seite, kurze Arrays nehmen 2 Bytes pro Element (zusätzlich zu vorne Platz für das Array + Objekt Buchhaltung).

Arrays

Der new-array opcode ruft dvmAllocArrayByClass (Zeile 71) Platz zuzuteilen. Dies ruft dann dvmAllocPrimitiveArray (Zeile 113) auf.In dem Schalter in dvmAllocPrimitiveArray wird der 'S' Fall für ein kurzes Array verwendet. Sie können sehen, es ruft allocArray (Zeile 38) mit Breite = 2.

Innerhalb allocArray, es macht die folgende Berechnung der Größe Größe des Arrays zu berechnen:

size_t elementShift = sizeof(size_t) * CHAR_BIT - 1 - CLZ(elemWidth); 
size_t elementSize = length << elementShift; 
size_t headerSize = OFFSETOF_MEMBER(ArrayObject, contents); 
size_t totalSize = elementSize + headerSize; 

Für einen kurzen, auf einem 32-Bit-System würde diese Berechnung sein:

size_t elementShift = (4 * 8) - 1 - 30; //== 1; 
size_t elementSize = length << 1; //i.e. length * 2 
size_t headerSize = <some constant value>; 
size_t totalSize = length*2 + <some constant value>; 

Kurze Arrays benötigen 2 Byte pro Element.

Felder

Der new-instance Opcode ruft dvmAllocObject (Linie 181) Platz für das neue Objekt zuzuordnen. Die zugewiesene Größe basiert auf dem Feld objectSize von ClassObject. objectSize wird in computeFieldOffsets (Zeile 3543) festgelegt. Wenn Sie jede Instanz von where FeldOffset in dieser Funktion inkrementiert finden, werden Sie bemerken, dass es immer in Schritten von 4 Bytes inkrementiert wird.

Kurze Felder benötigen 4 Byte.

+0

Dies ist genau die Art analytischer Antwort, die ich suchte. Vielen Dank! –

2

(Würde) ein Kommentar sein, aber es ist zu lang dafür.)

Es ist ziemlich Routine für 4-Byte-Felder für "kurze" lokale vars verwendet werden, da die JVM konzeptionell eine Maschine mit 4-Byte-Register und mit allen ist Der andere Müll in einem Stack-Frame macht keinen großen Unterschied. Zum Beispiel ist es wahrscheinlich, dass es von dem Kompromiss abhängt, Speicher zu sparen, anstatt Zyklen auf Verbreiterung und Ausrichtung auszugeben - Verbreiterung kostet oft einen kleinen Zyklus und sogar auf Architekturen, die angeblich "agnostisch" in Bezug auf die Grenzausrichtung sind es gibt normalerweise eine Strafe für einen Zugriff außerhalb der Grenzen, so dass "Pack" -Felder, ohne sie zuerst neu anzuordnen, um Wort-/Doppelwortgrenzen zu erhalten, die Leistung kosten können.

Wenn also die JVM "packen" will, ist im Allgemeinen die Neuanordnung der Felder erforderlich. Naive JVMs vermeiden Neuanordnungen, da dies mehrere Aspekte der JVM vereinfacht, aber (als ein Beispiel) auf AS/400 fanden wir, dass aggressive Neuordnung und Komprimierung von Instanzfeldern in der Größenordnung von 30% Leistungsverbesserung für speicherhungrige Anwendungen gewonnen wurden.

Ich habe noch nie die Innereien von Dalvik angesehen. Standard-Sun-abgeleitete JVMs sind historisch (nicht zuletzt neu betrachtet) abhängig vom Layout/der Reihenfolge der Dinge in der .class-Datei und daher nicht "natürlich" für eine Neuanordnung geeignet. Aber Dalvik stellt die .class-Datei wieder her und ist daher besser in der Lage, die Neuanordnung von Instanzenfeldern durchzuführen.

Hinweis: Um die Hypothese zu testen, dass Dalvik short Felder packt, müssen Sie eine Klasse mit mehreren Dutzend Instanzfeldern nacheinander erstellen und dann bestimmen, wie groß die resultierende Objektgröße ist. Erstellen Sie außerdem (unter der Annahme, dass die Packung im ersten Fall gesehen wird) eine Klasse mit den Feldern short und int (oder vielleicht long), die interleaved sind, um zu sehen, ob Dalvik sie neu anordnet, um eine Packung zu erzielen.