0
sizeof(new Object())how much memory objects take on JVMs. . . and when this may matterDawid WeissCarrot Search s.c.Poznań,...
.            Dawid Weiss        .            Likes coding            10 years assembly only    .       Likes research     ...
Memory
A byte    8 bits      7   6    5   4   3   2        1   0    2 nibbles           hi               lo    1 byte            ...
A byte (concrete value)    8 bits      1   1       1   0    0   0       1   1    2 nibbles           E                    ...
Memory (*)A linear sequence of bytes, each one at a certain offset(address), starting with 0.
hexdumpA textual dump of bytes from memory or le. May beaccompanied by (US-ASCII) character codes.
hexdumpA textual dump of bytes from memory or le. May beaccompanied by (US-ASCII) character codes.> hexdump -C jug.png0000...
Types in Java
Data types in JavaPrimitive types (non-objects).long, double, int, . . .Objects.Anything that requires new.Single-dimensio...
Primitives       type      required bytes       byte            1       boolean         1       char            2       sh...
Objectspublic class MyClass {  public boolean field1;  public int     field2;  public Object field3;}
Objectspublic class MyClass {  public boolean field1;  public int     field2;  public Object field3;}Whats sizeof(new MyCl...
Objectspublic class MyClass {  public boolean field1;  public int     field2;  public Object field3;}Whats sizeof(new MyCl...
Access to low-level Java
Low-level JavaRead the VM source code.If available (openjdk). Requires time.Instrumentation (agent).Provides getObjectSize...
Hexdumping Java objects
WARN: any of the code shown further on relies onundocumented and unspeci ed JVM internals and may not                work ...
Acquiring Unsafe instance like this:sun.misc.Unsafe.getUnsafe();java.lang.SecurityException: Unsafeat sun.misc.Unsafe.getU...
Acquiring Unsafe instance like this:sun.misc.Unsafe.getUnsafe();java.lang.SecurityException: Unsafeat sun.misc.Unsafe.getU...
Heres a snippet of Unsafe documentation:/** * Fetches a value from a given Java variable. * * More specifically, fetches a...
Heres a snippet of Unsafe documentation:/** * Fetches a value from a given Java variable. * * More specifically, fetches a...
public static class MyClass {      public byte field;      public MyClass(byte v) { field = v; }    }      @Test      publ...
public static class MyClass {      public byte field;      public MyClass(byte v) { field = v; }    }      @Test      publ...
public static class MyClassInt {      public int field;      public MyClassInt(int v) { field = v; }    }      @Test      ...
public static class MyClassInt {      public int field;      public MyClassInt(int v) { field = v; }    }      @Test      ...
Endianness (byte order)Affects multi-byte typesIntels typically little-endianOther processors big-endian or bi-endianYou ca...
Conclusions so farObject o1 = new MyClass((byte) 0xFE);Object o2 = new MyClass((byte) 0xFA);Object o3 = new MyClass((byte)...
Object header
openjdk/hotspot/src/share/vm/oops/oopsHierarchy.hpp
openjdk/hotspot/src/share/vm/oops/oopsHierarchy.hppclass oopDesc {  // ...  volatile markOop _mark;  union _metadata {    ...
openjdk/hotspot/src/share/vm/oops/oopsHierarchy.hppclass oopDesc {  // ...  volatile markOop _mark;  union _metadata {    ...
Lets do this:    Object o1 = new MyClass((byte) 0xfe);    System.out.println("Clean:");    System.out.println(BlackMagic.o...
on a 64-bit JVM:-- hashHeader(com.carrotsearch.sizeofexamples.E02_Header)Clean. [JVM: Java HotSpot(TM) 64-Bit Server VM, 2...
on a 64-bit JVM:-- hashHeader(com.carrotsearch.sizeofexamples.E02_Header)Clean. [JVM: Java HotSpot(TM) 64-Bit Server VM, 2...
on a 64-bit JVM:-- hashHeader(com.carrotsearch.sizeofexamples.E02_Header)Clean. [JVM: Java HotSpot(TM) 64-Bit Server VM, 2...
on a 64-bit JVM:-- hashHeader(com.carrotsearch.sizeofexamples.E02_Header)Clean. [JVM: Java HotSpot(TM) 64-Bit Server VM, 2...
Conclusions so farSystem hashCode is not a full int range (!).So hash collisions can be more frequent than needed.Memory c...
Fields
Unsafe can provide the "offset" of a eld relative to its base.    public static class MyClass {      public byte byteField ...
Unsafe can provide the "offset" of a eld relative to its base.    public static class MyClass {      public byte byteField ...
What will happen if we add elds of different types?public static class MyClass2 {  public byte byteField = (byte) 0xfe;  pu...
What will happen if we add elds of different types?public static class MyClass2 {  public byte byteField = (byte) 0xfe;  pu...
What will happen if we add elds of different types?public static class MyClass2 {  public byte byteField = (byte) 0xfe;  pu...
What will happen if we add elds of different types?public static class MyClass2 {  public byte byteField = (byte) 0xfe;  pu...
What happens if we have inheritance? Say:public static class MyClass2 {  public byte byteField = (byte) 0xfe;  public shor...
What happens if we have inheritance? Say:public static class MyClass2 {  public byte byteField = (byte) 0xfe;  public shor...
What happens if we have inheritance? Say:public static class MyClass2 {  public byte byteField = (byte) 0xfe;  public shor...
How about different VMs?public static class MyClass4 {  public byte byteField1 = (byte) 0x01;  public byte byteField2 = (by...
How about different VMs?public static class MyClass4 {  public byte byteField1 = (byte) 0x01;  public byte byteField2 = (by...
How about different VMs?public static class MyClass4 {  public byte byteField1 = (byte) 0x01;  public byte byteField2 = (by...
How about different VMs?public static class MyClass4 {  public byte byteField1 = (byte) 0x01;  public byte byteField2 = (by...
Conclusions so farField order and layout varies greatlyEach VM/hardware con g will have its own.Memory is "lost" on paddin...
Object alignment
How large is an object of MyClass (byte#)?public static class MyClass {  public byte byteField = (byte) 0xfe;}
How large is an object of MyClass (byte#)?public static class MyClass {  public byte byteField = (byte) 0xfe;}-- simpleFie...
How large is an object of MyClass (byte#)?public static class MyClass {  public byte byteField = (byte) 0xfe;}-- simpleFie...
How large is an object of MyClass (byte#)?public static class MyClass {  public byte byteField = (byte) 0xfe;}-- simpleFie...
How can we determine the size of object padding in use?                                                          .        ...
How can we determine the size of object padding in use?    On HotSpot:    com.sun.management.HotSpotDiagnosticMXBean mbean...
How can we determine the size of object padding in use?    On HotSpot:    com.sun.management.HotSpotDiagnosticMXBean mbean...
Wait. . . if its an option, can we change it?!-XX:ObjectAlignmentInBytes=32
Wait. . . if its an option, can we change it?!-XX:ObjectAlignmentInBytes=32-- simpleFieldOffset(com.carrotsearch.sizeofexa...
Wait. . . if its an option, can we change it?!-XX:ObjectAlignmentInBytes=32-- simpleFieldOffset(com.carrotsearch.sizeofexa...
Arrays and index scaling
ArraysThe same kind of analysis can be applied to arrays:• where is arrays length stored?• how are individual elements sto...
ArraysThe same kind of analysis can be applied to arrays:• where is arrays length stored?• how are individual elements sto...
False sharing
False sharingMemory split into cache lines64 bytes, typically. With multiple cache levels.Cache access speeds varyA lot!Fi...
An example (code simpli ed):    AtomicLongArray array = new AtomicLongArray(largeEnough);    for (int threads = 1; threads...
..
Conclusions so farFalse sharing is a real problem (?)If you have lots of concurrent operations.No low-level control in Jav...
Summary
Is any of this useful?
Is any of this useful?    Maybe not on a daily basis.
Is any of this useful?But try to estimate the "object overhead" of a large               HashMap<String,Byte>
HashMap<String,Byte> hm = Maps.newHashMap();hm.put("a", (byte) 1);hm.put("b", (byte) 2);hm.put("c", (byte) 3);System.out.p...
HashMap<String,Byte> hm = Maps.newHashMap();hm.put("a", (byte) 1);hm.put("b", (byte) 2);hm.put("c", (byte) 3);System.out.p...
java-sizeof            https://github.com/dweiss/java-sizeof       Ready-to-use code, including object hexdumper.Similar c...
Why the example needs a volatile?Holder holder = array[index];for (int i = 0; i < OPS; i++) {  holder.value++;}Non-volatil...
sizeof(Object): how much memory objects take on JVMs and when this may matter
sizeof(Object): how much memory objects take on JVMs and when this may matter
Upcoming SlideShare
Loading in...5
×

sizeof(Object): how much memory objects take on JVMs and when this may matter

17,260

Published on

How large (physically) are objects in Java? How are they stored? Can we hexdump an object in Java? All this and more.

Poznan JUG, May 2012.

Published in: Technology, Education
1 Comment
17 Likes
Statistics
Notes
  • + the corresponding code is here:
    https://github.com/dweiss/java-sizeof
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
17,260
On Slideshare
0
From Embeds
0
Number of Embeds
19
Actions
Shares
0
Downloads
104
Comments
1
Likes
17
Embeds 0
No embeds

No notes for slide

Transcript of "sizeof(Object): how much memory objects take on JVMs and when this may matter"

  1. 1. sizeof(new Object())how much memory objects take on JVMs. . . and when this may matterDawid WeissCarrot Search s.c.Poznań, May 2012
  2. 2. . Dawid Weiss . Likes coding 10 years assembly only . Likes research Former academic. PhD in IR. Likes open source Carrot2, HPPC, Lucene PMC, . . . Likes industry Carrot Search s.c.. .
  3. 3. Memory
  4. 4. A byte 8 bits 7 6 5 4 3 2 1 0 2 nibbles hi lo 1 byte byte
  5. 5. A byte (concrete value) 8 bits 1 1 1 0 0 0 1 1 2 nibbles E 3 1 byte E3
  6. 6. Memory (*)A linear sequence of bytes, each one at a certain offset(address), starting with 0.
  7. 7. hexdumpA textual dump of bytes from memory or le. May beaccompanied by (US-ASCII) character codes.
  8. 8. hexdumpA textual dump of bytes from memory or le. May beaccompanied by (US-ASCII) character codes.> hexdump -C jug.png00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR|00000010 00 00 01 30 00 00 00 96 08 02 00 00 00 d6 ab 43 |...0...........C|00000020 e3 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 |.....sRGB.......|00000030 2a a7 49 44 41 54 78 5e ed 5d 09 7c 14 45 d6 9f |*.IDATxˆ.].|.E..|00000040 7b 26 c9 24 90 20 09 24 a0 2e 09 02 2a e7 ba 20 |{&.$. .$....*.. |00000050 87 0a 2a 8a 28 ae 72 e8 ae 1c a2 0b 0a 22 0a 0a |..*.(.r......"..|...
  9. 9. Types in Java
  10. 10. Data types in JavaPrimitive types (non-objects).long, double, int, . . .Objects.Anything that requires new.Single-dimensional arrays of the above.Fixed size, max. 2 147 483 648 elements.
  11. 11. Primitives type required bytes byte 1 boolean 1 char 2 short 2 float 4 int 4 double 8 long 8
  12. 12. Objectspublic class MyClass { public boolean field1; public int field2; public Object field3;}
  13. 13. Objectspublic class MyClass { public boolean field1; public int field2; public Object field3;}Whats sizeof(new MyClass())?
  14. 14. Objectspublic class MyClass { public boolean field1; public int field2; public Object field3;}Whats sizeof(new MyClass())?This is considered VM implementation and hardware detail!(But sometimes wed like to know.)
  15. 15. Access to low-level Java
  16. 16. Low-level JavaRead the VM source code.If available (openjdk). Requires time.Instrumentation (agent).Provides getObjectSize estimate. Requires an agent at startup.sun.misc.UnsafeSUNs box of "only we can touch it" toys. Inherited by most other vendors (be-cause of sublicensing, for compatibility?).
  17. 17. Hexdumping Java objects
  18. 18. WARN: any of the code shown further on relies onundocumented and unspeci ed JVM internals and may not work or even compile.
  19. 19. Acquiring Unsafe instance like this:sun.misc.Unsafe.getUnsafe();java.lang.SecurityException: Unsafeat sun.misc.Unsafe.getUnsafe(Unsafe.java:68)at com.carrotsearch.sizeofexamples.UnsafeAccess.unsafe(UnsafeAccess.java:8)...
  20. 20. Acquiring Unsafe instance like this:sun.misc.Unsafe.getUnsafe();java.lang.SecurityException: Unsafeat sun.misc.Unsafe.getUnsafe(Unsafe.java:68)at com.carrotsearch.sizeofexamples.UnsafeAccess.unsafe(UnsafeAccess.java:8)..... . is a no-no. But we can access the static singleton:Class<?> unsafeClass = sun.misc.Unsafe.class;Field fld = unsafeClass.getDeclaredField("theUnsafe");fld.setAccessible(true);return (sun.misc.Unsafe) fld.get(null);
  21. 21. Heres a snippet of Unsafe documentation:/** * Fetches a value from a given Java variable. * * More specifically, fetches a field or array element within the given * object <code>o</code> at the given offset, or (if <code>o</code> is * null) from the memory address whose numerical value is the given * ... */public native int getByte(Object o, long offset);
  22. 22. Heres a snippet of Unsafe documentation:/** * Fetches a value from a given Java variable. * * More specifically, fetches a field or array element within the given * object <code>o</code> at the given offset, or (if <code>o</code> is * null) from the memory address whose numerical value is the given * ... */public native int getByte(Object o, long offset);How about if we hexdump around and beyond object o?
  23. 23. public static class MyClass { public byte field; public MyClass(byte v) { field = v; } } @Test public void simpleHexDumpByte() { Object o1 = new MyClass((byte) 0xFE); Object o2 = new MyClass((byte) 0xFA); Object o3 = new MyClass((byte) 0xF0); Unsafe unsafe = UnsafeAccess.unsafe(); for (long i = 0; i < 64;) { System.out.print(String.format("%02x ", unsafe.getByte(o1, i) & 0xFF)); if ((++i % 16) == 0) System.out.println(); } System.out.println(); } . E01 Alignments . ..
  24. 24. public static class MyClass { public byte field; public MyClass(byte v) { field = v; } } @Test public void simpleHexDumpByte() { Object o1 = new MyClass((byte) 0xFE); Object o2 = new MyClass((byte) 0xFA); Object o3 = new MyClass((byte) 0xF0); Unsafe unsafe = UnsafeAccess.unsafe(); for (long i = 0; i < 64;) { System.out.print(String.format("%02x ", unsafe.getByte(o1, i) & 0xFF)); if ((++i % 16) == 0) System.out.println(); } System.out.println(); } -- simpleHexDumpByte(com.carrotsearch.sizeofexamples.E01_Alignments) 01 00 00 00 00 00 00 00 60 a5 21 bd fe 00 00 00 01 00 00 00 00 00 00 00 60 a5 21 bd fa 00 00 00 01 00 00 00 00 00 00 00 60 a5 21 bd f0 00 00 00 01 00 00 00 00 00 00 00 f0 28 e1 bc 28 6d 88 eb . E01 Alignments . ..
  25. 25. public static class MyClassInt { public int field; public MyClassInt(int v) { field = v; } } @Test public void simpleHexDumpInt() { Object o1 = new MyClassInt(0xAABBCCDD); Object o2 = new MyClassInt(0x11223344); Unsafe unsafe = UnsafeAccess.unsafe(); for (long i = 0; i < 64;) { System.out.print(String.format("%02x ", unsafe.getByte(o1, i) & 0xFF)); if ((++i % 16) == 0) System.out.println(); } System.out.println(); } . E01 Alignments . ..
  26. 26. public static class MyClassInt { public int field; public MyClassInt(int v) { field = v; } } @Test public void simpleHexDumpInt() { Object o1 = new MyClassInt(0xAABBCCDD); Object o2 = new MyClassInt(0x11223344); Unsafe unsafe = UnsafeAccess.unsafe(); for (long i = 0; i < 64;) { System.out.print(String.format("%02x ", unsafe.getByte(o1, i) & 0xFF)); if ((++i % 16) == 0) System.out.println(); } System.out.println(); } -- simpleHexDumpInt(com.carrotsearch.sizeofexamples.E01_Alignments) 01 00 00 00 00 00 00 00 08 f6 21 bd dd cc bb aa 01 00 00 00 00 00 00 00 08 f6 21 bd 44 33 22 11 01 00 00 00 00 00 00 00 f0 df e5 bc 01 00 00 00 00 00 00 00 1a 00 00 00 78 1f ed bc 70 b1 21 bd . E01 Alignments . ..
  27. 27. Endianness (byte order)Affects multi-byte typesIntels typically little-endianOther processors big-endian or bi-endianYou cant assume anything about byte orderBut it is veri able -- java.nio.ByteOrder.
  28. 28. Conclusions so farObject o1 = new MyClass((byte) 0xFE);Object o2 = new MyClass((byte) 0xFA);Object o3 = new MyClass((byte) 0xF0);-- simpleHexDumpByte(com.carrotsearch.sizeofexamples.E01_Alignments)01 00 00 00 00 00 00 00 60 a5 21 bd fe 00 00 0001 00 00 00 00 00 00 00 60 a5 21 bd fa 00 00 0001 00 00 00 00 00 00 00 60 a5 21 bd f0 00 00 0001 00 00 00 00 00 00 00 f0 28 e1 bc 28 6d 88 ebWhat is before elds?Where does each eld start/end?What is the space "in between" objects?
  29. 29. Object header
  30. 30. openjdk/hotspot/src/share/vm/oops/oopsHierarchy.hpp
  31. 31. openjdk/hotspot/src/share/vm/oops/oopsHierarchy.hppclass oopDesc { // ... volatile markOop _mark; union _metadata { wideKlassOop _klass; narrowOop _compressed_klass; } _metadata; // ...
  32. 32. openjdk/hotspot/src/share/vm/oops/oopsHierarchy.hppclass oopDesc { // ... volatile markOop _mark; union _metadata { wideKlassOop _klass; narrowOop _compressed_klass; } _metadata; // ...// The markOop describes the header of an object.//// Note that the mark is not a real oop but just a word.// It is placed in the oop hierarchy for historical reasons.//// Bit-format of an object header (most significant first, big endian layout below)://// 32 bits:// --------// hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)// JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object)// size:32 ------------------------------------------>| (CMS free block)// PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)//// 64 bits:// --------// unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object)// JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object)// PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)// size:64 ----------------------------------------------------->| (CMS free block)//// unused:25 hash:31 -->| cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && normal object)// JavaThread*:54 epoch:2 cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && biased object)// narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted obj// unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)
  33. 33. Lets do this: Object o1 = new MyClass((byte) 0xfe); System.out.println("Clean:"); System.out.println(BlackMagic.objectMemoryAsString(o1)); System.out.println(String.format("After identity hash: %08x", System.identityHashCode(o1))); System.out.println(BlackMagic.objectMemoryAsString(o1)); . . E02 Header ..
  34. 34. on a 64-bit JVM:-- hashHeader(com.carrotsearch.sizeofexamples.E02_Header)Clean. [JVM: Java HotSpot(TM) 64-Bit Server VM, 21.0-b17, 1.7.0]0x0000 01 00 00 00 00 00 00 00 d8 dc 1b bd fe 00 00 00After identity hash: 7bf90a550x0000 01 55 0a f9 7b 00 00 00 d8 dc 1b bd fe 00 00 00
  35. 35. on a 64-bit JVM:-- hashHeader(com.carrotsearch.sizeofexamples.E02_Header)Clean. [JVM: Java HotSpot(TM) 64-Bit Server VM, 21.0-b17, 1.7.0]0x0000 01 00 00 00 00 00 00 00 d8 dc 1b bd fe 00 00 00After identity hash: 7bf90a550x0000 01 55 0a f9 7b 00 00 00 d8 dc 1b bd fe 00 00 00on a 32-bit JVM:-- hashHeader(com.carrotsearch.sizeofexamples.E02_Header)Clean. [JVM: Java HotSpot(TM) Server VM, 11.0-b16, 1.6.0_11]0x0000 01 00 00 00 90 5c 3d b2 fe 00 00 00 00 00 00 00After identity hash: 005e176f0x0000 81 b7 0b 2f 90 5c 3d b2 fe 00 00 00 00 00 00 00
  36. 36. on a 64-bit JVM:-- hashHeader(com.carrotsearch.sizeofexamples.E02_Header)Clean. [JVM: Java HotSpot(TM) 64-Bit Server VM, 21.0-b17, 1.7.0]0x0000 01 00 00 00 00 00 00 00 d8 dc 1b bd fe 00 00 00After identity hash: 7bf90a550x0000 01 55 0a f9 7b 00 00 00 d8 dc 1b bd fe 00 00 00on a 32-bit JVM:-- hashHeader(com.carrotsearch.sizeofexamples.E02_Header)Clean. [JVM: Java HotSpot(TM) Server VM, 11.0-b16, 1.6.0_11]0x0000 01 00 00 00 90 5c 3d b2 fe 00 00 00 00 00 00 00After identity hash: 005e176f0x0000 81 b7 0b 2f 90 5c 3d b2 fe 00 00 00 00 00 00 00(2f0bb781 >> 7 = 5e176f)
  37. 37. on a 64-bit JVM:-- hashHeader(com.carrotsearch.sizeofexamples.E02_Header)Clean. [JVM: Java HotSpot(TM) 64-Bit Server VM, 21.0-b17, 1.7.0]0x0000 01 00 00 00 00 00 00 00 d8 dc 1b bd fe 00 00 00After identity hash: 7bf90a550x0000 01 55 0a f9 7b 00 00 00 d8 dc 1b bd fe 00 00 00on a 32-bit JVM:-- hashHeader(com.carrotsearch.sizeofexamples.E02_Header)Clean. [JVM: Java HotSpot(TM) Server VM, 11.0-b16, 1.6.0_11]0x0000 01 00 00 00 90 5c 3d b2 fe 00 00 00 00 00 00 00After identity hash: 005e176f0x0000 81 b7 0b 2f 90 5c 3d b2 fe 00 00 00 00 00 00 00(2f0bb781 >> 7 = 5e176f)on a 64-bit JVM, full refs (-XX:-UseCompressedOops):-- hashHeader(com.carrotsearch.sizeofexamples.E02_Header)Clean. [JVM: Java HotSpot(TM) 64-Bit Server VM, 21.0-b17, 1.7.0]0x0000 01 00 00 00 00 00 00 00 d0 d6 eb a3 13 7f 00 000x0010 fe 00 00 00 00 00 00 00After identity hash: 7bf90a550x0000 01 55 0a f9 7b 00 00 00 d0 d6 eb a3 13 7f 00 000x0010 fe 00 00 00 00 00 00 00
  38. 38. Conclusions so farSystem hashCode is not a full int range (!).So hash collisions can be more frequent than needed.Memory consumption may varyDepending on architecture and settings.Compact OOPs are an immediate gain.And theyre fast -- we will see why later.
  39. 39. Fields
  40. 40. Unsafe can provide the "offset" of a eld relative to its base. public static class MyClass { public byte byteField = (byte) 0xfe; } Object o1 = new MyClass(); System.out.println(BlackMagic.objectMemoryAsString(o1)); Unsafe unsafe = UnsafeAccess.unsafe(); System.out.println( "byteField offset: " + unsafe.objectFieldOffset(MyClass.class.getDeclaredField("byteField"))); . . E03 Fields ..
  41. 41. Unsafe can provide the "offset" of a eld relative to its base. public static class MyClass { public byte byteField = (byte) 0xfe; } Object o1 = new MyClass(); System.out.println(BlackMagic.objectMemoryAsString(o1)); Unsafe unsafe = UnsafeAccess.unsafe(); System.out.println( "byteField offset: " + unsafe.objectFieldOffset(MyClass.class.getDeclaredField("byteField"))); -- simpleFieldOffset(com.carrotsearch.sizeofexamples.E03_Fields) 0x0000 01 00 00 00 00 00 00 00 82 3c 64 ef fe 00 00 00 byteField offset: 12 . . E03 Fields ..
  42. 42. What will happen if we add elds of different types?public static class MyClass2 { public byte byteField = (byte) 0xfe; public short shortField = (short) 0xaabb; public long longField = 0x1122334455667788L;}
  43. 43. What will happen if we add elds of different types?public static class MyClass2 { public byte byteField = (byte) 0xfe; public short shortField = (short) 0xaabb; public long longField = 0x1122334455667788L;}-- twoFieldOffsets(com.carrotsearch.sizeofexamples.E03_Fields)0x0000 01 00 00 00 00 00 00 00 59 3a 68 ef bb aa fe 000x0010 88 77 66 55 44 33 22 11byteField offset: 14shortField offset: 12longField offset: 16
  44. 44. What will happen if we add elds of different types?public static class MyClass2 { public byte byteField = (byte) 0xfe; public short shortField = (short) 0xaabb; public long longField = 0x1122334455667788L;}-- twoFieldOffsets(com.carrotsearch.sizeofexamples.E03_Fields)0x0000 01 00 00 00 00 00 00 00 59 3a 68 ef bb aa fe 000x0010 88 77 66 55 44 33 22 11byteField offset: 14shortField offset: 12longField offset: 16Note the gap at offset 15 -- longs are aligned (in this JVM).
  45. 45. What will happen if we add elds of different types?public static class MyClass2 { public byte byteField = (byte) 0xfe; public short shortField = (short) 0xaabb; public long longField = 0x1122334455667788L;}-- twoFieldOffsets(com.carrotsearch.sizeofexamples.E03_Fields)0x0000 01 00 00 00 00 00 00 00 59 3a 68 ef bb aa fe 000x0010 88 77 66 55 44 33 22 11byteField offset: 14shortField offset: 12longField offset: 16Note the gap at offset 15 -- longs are aligned (in this JVM).Think of what the gap would be if we just had a long eld?
  46. 46. What happens if we have inheritance? Say:public static class MyClass2 { public byte byteField = (byte) 0xfe; public short shortField = (short) 0xaabb; public long longField = 0x1122334455667788L;}public static class MyClass3 extends MyClass2 { public byte byteField2 = (byte) 0xfa;}
  47. 47. What happens if we have inheritance? Say:public static class MyClass2 { public byte byteField = (byte) 0xfe; public short shortField = (short) 0xaabb; public long longField = 0x1122334455667788L;}public static class MyClass3 extends MyClass2 { public byte byteField2 = (byte) 0xfa;}-- inheritedFields(com.carrotsearch.sizeofexamples.E03_Fields)0x0000 01 00 00 00 00 00 00 00 3d 8f 67 ef bb aa fe 000x0010 88 77 66 55 44 33 22 11 ff 00 00 00 00 00 00 00byteField2 offset: 24byteField offset: 14shortField offset: 12longField offset: 16
  48. 48. What happens if we have inheritance? Say:public static class MyClass2 { public byte byteField = (byte) 0xfe; public short shortField = (short) 0xaabb; public long longField = 0x1122334455667788L;}public static class MyClass3 extends MyClass2 { public byte byteField2 = (byte) 0xfa;}-- inheritedFields(com.carrotsearch.sizeofexamples.E03_Fields)0x0000 01 00 00 00 00 00 00 00 3d 8f 67 ef bb aa fe 000x0010 88 77 66 55 44 33 22 11 ff 00 00 00 00 00 00 00byteField2 offset: 24byteField offset: 14shortField offset: 12longField offset: 16But: IBMs J9 can "pack" elds in an inheritance hierarchy.
  49. 49. How about different VMs?public static class MyClass4 { public byte byteField1 = (byte) 0x01; public byte byteField2 = (byte) 0x02; public byte byteField3 = (byte) 0x03; public byte byteField4 = (byte) 0x04; public short shortField = (short) 0xa1a2; public long longField = 0xb1b2b3b4b5b6b7b8L;}
  50. 50. How about different VMs?public static class MyClass4 { public byte byteField1 = (byte) 0x01; public byte byteField2 = (byte) 0x02; public byte byteField3 = (byte) 0x03; public byte byteField4 = (byte) 0x04; public short shortField = (short) 0xa1a2; public long longField = 0xb1b2b3b4b5b6b7b8L;}-- vmVariance(com.carrotsearch.sizeofexamples.E03_Fields)[JVM: Oracle JRockit(R), R28.2.3-13-149708-1.6.0_31-20120327-1523-windows-x86_64]0x0000 e0 2f 47 02 00 00 00 00 b8 b7 b6 b5 b4 b3 b2 b10x0010 a2 a1 01 02 03 04 00 00
  51. 51. How about different VMs?public static class MyClass4 { public byte byteField1 = (byte) 0x01; public byte byteField2 = (byte) 0x02; public byte byteField3 = (byte) 0x03; public byte byteField4 = (byte) 0x04; public short shortField = (short) 0xa1a2; public long longField = 0xb1b2b3b4b5b6b7b8L;}-- vmVariance(com.carrotsearch.sizeofexamples.E03_Fields)[JVM: Oracle JRockit(R), R28.2.3-13-149708-1.6.0_31-20120327-1523-windows-x86_64]0x0000 e0 2f 47 02 00 00 00 00 b8 b7 b6 b5 b4 b3 b2 b10x0010 a2 a1 01 02 03 04 00 00-- vmVariance(com.carrotsearch.sizeofexamples.E03_Fields)[JVM: Java HotSpot(TM) 64-Bit Server VM, 22.1-b02, Oracle Corporation, Oracle Corporation, 1.0x0000 01 00 00 00 00 00 00 00 44 90 67 ef a2 a1 01 020x0010 b8 b7 b6 b5 b4 b3 b2 b1 03 04 00 00 00 00 00 00
  52. 52. How about different VMs?public static class MyClass4 { public byte byteField1 = (byte) 0x01; public byte byteField2 = (byte) 0x02; public byte byteField3 = (byte) 0x03; public byte byteField4 = (byte) 0x04; public short shortField = (short) 0xa1a2; public long longField = 0xb1b2b3b4b5b6b7b8L;}-- vmVariance(com.carrotsearch.sizeofexamples.E03_Fields)[JVM: Oracle JRockit(R), R28.2.3-13-149708-1.6.0_31-20120327-1523-windows-x86_64]0x0000 e0 2f 47 02 00 00 00 00 b8 b7 b6 b5 b4 b3 b2 b10x0010 a2 a1 01 02 03 04 00 00-- vmVariance(com.carrotsearch.sizeofexamples.E03_Fields)[JVM: Java HotSpot(TM) 64-Bit Server VM, 22.1-b02, Oracle Corporation, Oracle Corporation, 1.0x0000 01 00 00 00 00 00 00 00 44 90 67 ef a2 a1 01 020x0010 b8 b7 b6 b5 b4 b3 b2 b1 03 04 00 00 00 00 00 00-- vmVariance(com.carrotsearch.sizeofexamples.E03_Fields)[JVM: IBM J9 VM, 2.4, IBM Corporation, IBM Corporation, 1.6.0]0x0000 b0 6a 7f 6b 0e 80 a6 43 00 00 00 00 b8 b7 b6 b50x0010 b4 b3 b2 b1 01 00 00 00 02 00 00 00 03 00 00 000x0020 04 00 00 00 a2 a1 ff ff(note byte elds are also padded on J9!).
  53. 53. Conclusions so farField order and layout varies greatlyEach VM/hardware con g will have its own.Memory is "lost" on paddingsVMs try to reorder and pack elds though.Paddings are not useless crapVM designers are machine code experts!
  54. 54. Object alignment
  55. 55. How large is an object of MyClass (byte#)?public static class MyClass { public byte byteField = (byte) 0xfe;}
  56. 56. How large is an object of MyClass (byte#)?public static class MyClass { public byte byteField = (byte) 0xfe;}-- simpleFieldOffset(com.carrotsearch.sizeofexamples.E03_Fields)0x0000 01 00 00 00 00 00 00 00 82 3c 64 ef fe 00 00 00byteField offset: 12
  57. 57. How large is an object of MyClass (byte#)?public static class MyClass { public byte byteField = (byte) 0xfe;}-- simpleFieldOffset(com.carrotsearch.sizeofexamples.E03_Fields)0x0000 01 00 00 00 00 00 00 00 82 3c 64 ef fe 00 00 00byteField offset: 12Objects are placed on a "grid" of aligned addresses.
  58. 58. How large is an object of MyClass (byte#)?public static class MyClass { public byte byteField = (byte) 0xfe;}-- simpleFieldOffset(com.carrotsearch.sizeofexamples.E03_Fields)0x0000 01 00 00 00 00 00 00 00 82 3c 64 ef fe 00 00 00byteField offset: 12Objects are placed on a "grid" of aligned addresses.Efficient compact references: address scaling by a constant.
  59. 59. How can we determine the size of object padding in use? . E04 Paddings . ..
  60. 60. How can we determine the size of object padding in use? On HotSpot: com.sun.management.HotSpotDiagnosticMXBean mbean = (HotSpotDiagnosticMXBean) ManagementFactory.newPlatformMXBeanProxy( ManagementFactory.getPlatformMBeanServer(), "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); System.out.println("ObjectAlignment: " + mbean.getVMOption("ObjectAlignmentInBytes").getValue()); System.out.println(BlackMagic.objectMemoryAsString(new Object())); . E04 Paddings . ..
  61. 61. How can we determine the size of object padding in use? On HotSpot: com.sun.management.HotSpotDiagnosticMXBean mbean = (HotSpotDiagnosticMXBean) ManagementFactory.newPlatformMXBeanProxy( ManagementFactory.getPlatformMBeanServer(), "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); System.out.println("ObjectAlignment: " + mbean.getVMOption("ObjectAlignmentInBytes").getValue()); System.out.println(BlackMagic.objectMemoryAsString(new Object())); -- simpleFieldOffset(com.carrotsearch.sizeofexamples.E04_Paddings) ObjectAlignment: 8 0x0000 01 00 00 00 00 00 00 00 cb 11 5c ef 00 00 00 00 . E04 Paddings . ..
  62. 62. Wait. . . if its an option, can we change it?!-XX:ObjectAlignmentInBytes=32
  63. 63. Wait. . . if its an option, can we change it?!-XX:ObjectAlignmentInBytes=32-- simpleFieldOffset(com.carrotsearch.sizeofexamples.E04_Paddings)ObjectAlignment: 320x0000 01 00 00 00 00 00 00 00 76 05 d7 fb 00 00 00 000x0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  64. 64. Wait. . . if its an option, can we change it?!-XX:ObjectAlignmentInBytes=32-- simpleFieldOffset(com.carrotsearch.sizeofexamples.E04_Paddings)ObjectAlignment: 320x0000 01 00 00 00 00 00 00 00 76 05 d7 fb 00 00 00 000x0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00Not smaller than 8 though (remember - compact oops scaling!).error: ObjectAlignmentInBytes=4 must be greater or equal 8
  65. 65. Arrays and index scaling
  66. 66. ArraysThe same kind of analysis can be applied to arrays:• where is arrays length stored?• how are individual elements stored?• are there any paddings?
  67. 67. ArraysThe same kind of analysis can be applied to arrays:• where is arrays length stored?• how are individual elements stored?• are there any paddings?This is your homework :)
  68. 68. False sharing
  69. 69. False sharingMemory split into cache lines64 bytes, typically. With multiple cache levels.Cache access speeds varyA lot!Fields or even objects can share a cache line.Multithreaded access to con icting cache lines will slow down apps.
  70. 70. An example (code simpli ed): AtomicLongArray array = new AtomicLongArray(largeEnough); for (int threads = 1; threads <= 8; threads++) for (int sepIndexes : new int [] {0, 0, 0, 1, .... 8, 9, 10, 11, 12, 13, 1000}) runRound(threads, sepIndexes); runRound(N, sep) { // start N threads, each reading/ writing to // array[threads_index * sep] } . E05 FalseSharing . ..
  71. 71. ..
  72. 72. Conclusions so farFalse sharing is a real problem (?)If you have lots of concurrent operations.No low-level control in Java (without JNI)Thread-core affinity, cache line alignments.Array traversals may be tricky!Built-in bounds checking may cause false sharing (unless eliminated).
  73. 73. Summary
  74. 74. Is any of this useful?
  75. 75. Is any of this useful? Maybe not on a daily basis.
  76. 76. Is any of this useful?But try to estimate the "object overhead" of a large HashMap<String,Byte>
  77. 77. HashMap<String,Byte> hm = Maps.newHashMap();hm.put("a", (byte) 1);hm.put("b", (byte) 2);hm.put("c", (byte) 3);System.out.println(ObjectTree.dump(hm));
  78. 78. HashMap<String,Byte> hm = Maps.newHashMap();hm.put("a", (byte) 1);hm.put("b", (byte) 2);hm.put("c", (byte) 3);System.out.println(ObjectTree.dump(hm));-- hashMapTree(com.carrotsearch.sizeofexamples.E08_HashMapTree) 440 48 root => <HashMap#0> 0 0 +- Set entrySet => null 0 0 +- Set keySet => null 392 80 +- Entry[] table => Entry[] 104 32 | +- [4] => <Entry#2> 56 32 | | +- Object key => <String#3> 24 24 | | | +- char[] value => char[] 0 0 | | +- Entry next => null 16 16 | | +- Object value => <Byte#5> 104 32 | +- [5] => <Entry#6> 56 32 | | +- Object key => <String#7> 24 24 | | | +- char[] value => char[] 0 0 | | +- Entry next => null 16 16 | | +- Object value => <Byte#9> 104 32 | +- [7] => <Entry#10> 56 32 | +- Object key => <String#11> 24 24 | | +- char[] value => char[] 0 0 | +- Entry next => null 16 16 | +- Object value => <Byte#13> 0 0 +- Collection values => null
  79. 79. java-sizeof https://github.com/dweiss/java-sizeof Ready-to-use code, including object hexdumper.Similar code in Apache Lucene (joint work with Uwe Schindler).
  80. 80. Why the example needs a volatile?Holder holder = array[index];for (int i = 0; i < OPS; i++) { holder.value++;}Non-volatile eld: 0x00007f86928087c4: mov %r11d,%ecx 0x00007f86928087c7: add %r8d,%ecx 0x00007f86928087ca: inc %r11d 0x00007f86928087cd: inc %ecx 0x00007f86928087cf: mov %ecx,0xc(%r10) 0x00007f86928087d3: cmp $0x989680,%r11d 0x00007f86928087da: jl 0x00007f86928087c4Volatile eld: 0x00007fe2ba6e8208: mov 0xc(%r10),%r8d 0x00007fe2ba6e820c: inc %r11d 0x00007fe2ba6e820f: inc %r8d 0x00007fe2ba6e8212: mov %r8d,0xc(%r10) 0x00007fe2ba6e8216: lock addl $0x0,(%rsp) 0x00007fe2ba6e821b: cmp $0x989680,%r11d 0x00007fe2ba6e8222: jl 0x00007fe2ba6e8208
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×