Rekurzivní sizeOf pro JVM

Při svém tažení za porozuměním jak JVM pracuje s pamětí jsem si napsal jednoduchý program, který rekurzivně spočítá velikost objektu a všech jeho komponent.

Když chci zjistit velikost instance Vectoru obsahujícího 500 elementů, udělám to jednoduše:

val vect = scala.collection.immutable.Vector(1 to 500: _*)
SizeOf.sizeOfStats(vect)

Výstupem pak bude něco ve smyslu:

total 10504

java.lang.Integer
12 java.lang.Integer.value: int
16

scala.collection.immutable.Vector
12 scala.collection.immutable.Vector.startIndex: int
16 scala.collection.immutable.Vector.endIndex: int
20 scala.collection.immutable.Vector.focus: int
24 scala.collection.immutable.Vector.depth: int
28 scala.collection.immutable.Vector.dirty: boolean
32 scala.collection.immutable.Vector.display0: [Ljava.lang.Object;
36 scala.collection.immutable.Vector.display1: [Ljava.lang.Object;
40 scala.collection.immutable.Vector.display2: [Ljava.lang.Object;
44 scala.collection.immutable.Vector.display3: [Ljava.lang.Object;
48 scala.collection.immutable.Vector.display4: [Ljava.lang.Object;
52 scala.collection.immutable.Vector.display5: [Ljava.lang.Object;
56

  count      one         sum
----------------------------
     17     144B       2448B [Ljava.lang.Object;
    500      16B       8000B java.lang.Integer
      1      56B         56B scala.collection.immutable.Vector
----------------------------
    518      72B      10504B

Z výstupu je patrné několik věcí:

  • Celková velikost objektu je 10504 bajtů.
  • Při procházení objektového grafu program narazil na třídy Integer a Vector. Integer má jeden atribut value typu int na offsetu 12 a celková velikost třídy je 16 bajtů. Vector má 11 atributů: inty, boolean a pole objektů.
  • Celkem prošel 17 polí objektů (jedno v průměru zabíralo 144 bajtů a v součtu 2448 bajtů), 500 objektů Integer a 1 objekt Vector.
  • Dohromady viděl 518 objektů, jeden měl v průměru 72 bajtů a dohromady zabraly oněch 10504 bajtů.

Nedostanu tedy jenom jedno číslo, ale i pohled pod kapotu, z čeho je objekt složen uvnitř. Program si poradí s cyklickým objektovým grafem. Jednotlivé objekty od sebe rozlišuje pomocí jejich identityHashCode. To sice není unikátní, ale pro rozumně malé objekty se dá počítat s tím, že výsledek bude přesný.

Příště s tímhle udělátkem provedu několik měření, jak jsou na tom kolekce s hladem po paměti.


Zdrojové kódy jsou dostupné na githubu.

Flattr this!

This entry was posted in Java, JVM, Paměť, Scala. Bookmark the permalink.

2 Responses to Rekurzivní sizeOf pro JVM

  1. v6ak says:

    Proč identityHashCode? Proč ne přímo reference na objekty?

    • Udělal jsem to proto, že všechny kolekce pro porovnání elementů používají equals a ne rovnost referencí. Ale teď jsem narazil na java.util.IdentityHashMap a to by se dalo.

Leave a Reply

Your email address will not be published. Required fields are marked *