The bytecode hocus pocus - JavaOne 2016

174
@rrafols The bytecode hocus-pocus #perfmatters

Transcript of The bytecode hocus pocus - JavaOne 2016

Page 1: The bytecode hocus pocus - JavaOne 2016

@rrafols

The bytecodehocus-pocus

#perfmatters

Page 2: The bytecode hocus pocus - JavaOne 2016

@rrafols

DisclaimerThis presentation contains bytecode

Content is my own experimentation and might differ on other environments

Page 3: The bytecode hocus pocus - JavaOne 2016

@rrafols

Competitions

Work

2015 Local winner2016 Ambassador

Runner up

Demoscene

Speaker

Author Entrerpreneurship

About me

Page 4: The bytecode hocus pocus - JavaOne 2016

@rrafols

Our friend the java compiler

Page 5: The bytecode hocus pocus - JavaOne 2016

@rrafols

*.java → [javac] → *.class

Page 6: The bytecode hocus pocus - JavaOne 2016

@rrafols

Or, for example, on Android

Page 7: The bytecode hocus pocus - JavaOne 2016

@rrafols

*.java → [javac] → *.class

*.class → [dx] → dex file

Page 8: The bytecode hocus pocus - JavaOne 2016

@rrafols

*.java → [javac] → *.class*.class → [dx] → dex

dex → [dexopt] → optimized dexdex → [dex2oat] → optimized native

Page 9: The bytecode hocus pocus - JavaOne 2016

@rrafols

but change is coming!Jack & Jill

Page 10: The bytecode hocus pocus - JavaOne 2016

@rrafols

*.java → [jack] → dex file

Page 11: The bytecode hocus pocus - JavaOne 2016

@rrafols

Let’s focus on javacJavac vs other compilers

Page 12: The bytecode hocus pocus - JavaOne 2016

@rrafols

Compilers

Produces optimized code for the target platform

Page 13: The bytecode hocus pocus - JavaOne 2016

@rrafols

Javac

Does not produce optimized code*

Page 14: The bytecode hocus pocus - JavaOne 2016

@rrafols

Javac

Does not know on which architecture the code will be

executed

Page 15: The bytecode hocus pocus - JavaOne 2016

@rrafols

Source: Oracle

Page 16: The bytecode hocus pocus - JavaOne 2016

@rrafols

For this reason

Java bytecode & operations are stack based

Page 17: The bytecode hocus pocus - JavaOne 2016

@rrafols

Easy to interpret

But not the most optimal solution

(regarding performance)

Page 18: The bytecode hocus pocus - JavaOne 2016

@rrafols

Quick example

Stack based integer addition

Page 19: The bytecode hocus pocus - JavaOne 2016

@rrafols

j = j + i

Page 20: The bytecode hocus pocus - JavaOne 2016

@rrafols

Java bytecode

Page 21: The bytecode hocus pocus - JavaOne 2016

@rrafols

iload_3

iload_2

iadd

istore_2

Page 22: The bytecode hocus pocus - JavaOne 2016

@rrafols

Register based approach

Page 23: The bytecode hocus pocus - JavaOne 2016

@rrafols

add r01, r02, r01

or

add eax, ebx

Page 24: The bytecode hocus pocus - JavaOne 2016

@rrafols

Let’s make things interesting…

j = j + i + k + w + h * 2 + p * p;

Page 25: The bytecode hocus pocus - JavaOne 2016

@rrafols

Java bytecode

Page 26: The bytecode hocus pocus - JavaOne 2016

@rrafols

0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 510: iconst_211: imul12: iadd13: iload 615: iload 617: imul18: iadd19: istore_2

j = j + i + k + w + h * 2 + p * p;

Local vars1: i2: j3: k4: w5: h6: p

Page 27: The bytecode hocus pocus - JavaOne 2016

@rrafols

0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 510: iconst_211: imul12: iadd13: iload 615: iload 617: imul18: iadd19: istore_2

j = j + i + k + w + h * 2 + p * p;

Local vars1: i2: j3: k4: w5: h6: p

Page 28: The bytecode hocus pocus - JavaOne 2016

@rrafols

0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 510: iconst_211: imul12: iadd13: iload 615: iload 617: imul18: iadd19: istore_2

j = j + i + k + w + h * 2 + p * p;

Local vars1: i2: j3: k4: w5: h6: p

Page 29: The bytecode hocus pocus - JavaOne 2016

@rrafols

0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 510: iconst_211: imul12: iadd13: iload 615: iload 617: imul18: iadd19: istore_2

j = j + i + k + w + h * 2 + p * p;

Local vars1: i2: j3: k4: w5: h6: p

Page 30: The bytecode hocus pocus - JavaOne 2016

@rrafols

0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 510: iconst_211: imul12: iadd13: iload 615: iload 617: imul18: iadd19: istore_2

j = j + i + k + w + h * 2 + p * p;

Local vars1: i2: j3: k4: w5: h6: p

Page 31: The bytecode hocus pocus - JavaOne 2016

@rrafols

0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 510: iconst_211: imul12: iadd13: iload 615: iload 617: imul18: iadd19: istore_2

j = j + i + k + w + h * 2 + p * p;

Local vars1: i2: j3: k4: w5: h6: p

Page 32: The bytecode hocus pocus - JavaOne 2016

@rrafols

0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 510: iconst_211: imul12: iadd13: iload 615: iload 617: imul18: iadd19: istore_2

j = j + i + k + w + h * 2 + p * p;

Local vars1: i2: j3: k4: w5: h6: p

Page 33: The bytecode hocus pocus - JavaOne 2016

@rrafols

Register based approach

Page 34: The bytecode hocus pocus - JavaOne 2016

@rrafols

add r01, r02, r01add r01, r03, r01add r01, r04, r01mul r07, r05, #2add r01, r07, r01mul r08, r06, r06add r02, r08, r01

j = j + i + k + w + h * 2 + p * p;

r01: ir02: jr03: kr04: wr05: hr06: p

Page 35: The bytecode hocus pocus - JavaOne 2016

@rrafols

Java VM (JVM)

Only the JVM knows on which architecture is running. In this

case, for example, we used up to 8 registers

Page 36: The bytecode hocus pocus - JavaOne 2016

@rrafols

Java VM (JVM)

All optimizations are left to be done by the JVM

Page 37: The bytecode hocus pocus - JavaOne 2016

@rrafols

Maybe takes this concept a bit too far...

Page 38: The bytecode hocus pocus - JavaOne 2016

@rrafols

Imagine this simple C code#include <stdio.h>

int main() {

int a = 10;

int b = 1 + 2 + 3 + 4 + 5 + 6 + a;

printf("%d\n", b);

}

Page 39: The bytecode hocus pocus - JavaOne 2016

@rrafols

GCC compiler#include <stdio.h>

int main() {

int a = 10;

int b = 1 + 2 + 3 + 4 + 5 + 6 + a;

printf("%d\n", b);

}

movl $31, %esicall _printf

* Using gcc & -O2 compiler option

Page 40: The bytecode hocus pocus - JavaOne 2016

@rrafols

javac

public static void main(String args[]) {

int a = 10;

int b = 1 + 2 + 3 + 4 + 5 + 6 + a;

System.out.println(b);

}

0: bipush 10

2: istore_1

3: bipush 21

5: iload_1

6: iadd

7: istore_2

...

Page 41: The bytecode hocus pocus - JavaOne 2016

@rrafols

Let's do a small change#include <stdio.h>

int main() {

int a = 10;

int b = 1 + 2 + 3 + 4 + 5 + a + 6;

printf("%d\n", b);

}

Page 42: The bytecode hocus pocus - JavaOne 2016

@rrafols

GCC compiler#include <stdio.h>

int main() {

int a = 10;

int b = 1 + 2 + 3 + 4 + 5 + a + 6;

printf("%d\n", b);

}

movl $31, %esicall _printf

* Using gcc & -O2 compiler option

Page 43: The bytecode hocus pocus - JavaOne 2016

@rrafols

javac

public static void main(String args[]) {

int a = 10;

int b = 1 + 2 + 3 + 4 + 5 + a + 6;

System.out.println(b);

}

0: bipush 10

2: istore_1

3: bipush 155: iload_1 6: iadd 7: bipush 69: iadd 10: istore_2

...

Page 44: The bytecode hocus pocus - JavaOne 2016

@rrafols

Let's do another quick change..

public static void main(String args[]) {

int a = 10;

int b = a + 1 + 2 + 3 + 4 + 5 + 6;

System.out.println(b);

}

Page 45: The bytecode hocus pocus - JavaOne 2016

@rrafols

javac

public static void main(String args[]) {

int a = 10;

int b = a + 1 + 2 + 3 + 4 + 5 + 6;

System.out.println(b);

}

0: bipush 10

2: istore_1

3: iload_1

4: iconst_1

5: iadd

6: iconst_2

7: iadd

8: iconst_3

9: iadd

10: iconst_4

11: iadd

12: iconst_5

13: iadd

14: bipush 6

16: iadd

17: istore_2

...

Page 46: The bytecode hocus pocus - JavaOne 2016

@rrafols

On Android there is jack to the rescue...

Page 47: The bytecode hocus pocus - JavaOne 2016

@rrafols

jack

public static void main(String args[]) {

int a = 10;

int b = a + 1 + 2 + 3 + 4 + 5 + 6;

System.out.println(b);

}

...

0: const/16 v0, #int 312: sget-object v1, Ljava/lang/System;

4: invoke-virtual {v1, v0}

7: return-void

...

Page 48: The bytecode hocus pocus - JavaOne 2016

@rrafols

And on Java there is the JIT compiler to the rescue

Page 49: The bytecode hocus pocus - JavaOne 2016

@rrafols

JIT assembly outputpublic static void main(String args[]) {

int a = 10;

int b = a + 1 + 2 + 3 + 4 + 5 + 6;

System.out.println(b);

}

...

0x00000001104b2bff: mov    eax, 0x000000000000001f...

0: bipush 10

2: istore_1

3: iload_1

4: iconst_1

5: iadd

6: iconst_2

7: iadd

8: iconst_3

9: iadd

10: iconst_4

11: iadd

12: iconst_5

13: iadd

14: bipush 6

16: iadd

17: istore_2

...

Page 50: The bytecode hocus pocus - JavaOne 2016

@rrafols

Compilers

Produces optimised code for target platform

Page 51: The bytecode hocus pocus - JavaOne 2016

@rrafols

Language additions

Thinks to consider

Page 52: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxing

Transparent to the developer but compiler adds some 'extra' code

Page 53: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxinglong total = 0;for(int i = 0; i < N; i++) { total += i;}

 0: lconst_0 1: lstore_1 2: iconst_0 3: istore_3 4: iload_3 5: ldc #8     // N 7: if_icmpge 2110: lload_111: iload_312: i2l13: ladd14: lstore_115: iinc 3, 118: goto 4

Page 54: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxinglong total = 0;for(int i = 0; i < N; i++) { total += i;}

 0: lconst_0 1: lstore_1 2: iconst_0 3: istore_3 4: iload_3 5: ldc #8     // N 7: if_icmpge 2110: lload_111: iload_312: i2l13: ladd14: lstore_115: iinc 3, 118: goto 4

Page 55: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxinglong total = 0;for(int i = 0; i < N; i++) { total += i;}

 0: lconst_0 1: lstore_1 2: iconst_0 3: istore_3 4: iload_3 5: ldc #8     // N 7: if_icmpge 2110: lload_111: iload_312: i2l13: ladd14: lstore_115: iinc 3, 118: goto 4

Page 56: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxinglong total = 0;for(int i = 0; i < N; i++) { total += i;}

 0: lconst_0 1: lstore_1 2: iconst_0 3: istore_3 4: iload_3 5: ldc #8     // N 7: if_icmpge 2110: lload_111: iload_312: i2l13: ladd14: lstore_115: iinc 3, 118: goto 421:

Page 57: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxinglong total = 0;for(int i = 0; i < N; i++) { total += i;}

 0: lconst_0 1: lstore_1 2: iconst_0 3: istore_3 4: iload_3 5: ldc #8     // N 7: if_icmpge 2110: lload_111: iload_312: i2l13: ladd14: lstore_115: iinc 3, 118: goto 4

Page 58: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxinglong total = 0;for(int i = 0; i < N; i++) { total += i;}

 0: lconst_0 1: lstore_1 2: iconst_0 3: istore_3 4: iload_3 5: ldc #8     // N 7: if_icmpge 2110: lload_111: iload_312: i2l13: ladd14: lstore_115: iinc 3, 118: goto 4

Page 59: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxinglong total = 0;for(int i = 0; i < N; i++) { total += i;}

 0: lconst_0 1: lstore_1 2: iconst_0 3: istore_3 4: iload_3 5: ldc #8     // N 7: if_icmpge 2110: lload_111: iload_312: i2l13: ladd14: lstore_115: iinc 3, 118: goto 4

Page 60: The bytecode hocus pocus - JavaOne 2016

@rrafols

AutoboxingLong total = 0;for(Integer i = 0; i < N; i++) { total += i;}

Page 61: The bytecode hocus pocus - JavaOne 2016

@rrafols

AutoboxingLong total = 0;for(Integer i = 0; i < N; i++) { total += i;}

0: lconst_0 1: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;4: astore_1 5: iconst_0 6: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;9: astore_2 10: aload_2 11: invokevirtual #9 // Method java/lang/Integer.intValue:()I14: sipush N17: if_icmpge 5420: aload_1 21: invokevirtual #10 // Method java/lang/Long.longValue:()J24: aload_2 25: invokevirtual #9 // Method java/lang/Integer.intValue:()I28: i2l 29: ladd 30: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // Method java/lang/Integer.intValue:()I40: iconst_1 41: iadd 42: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;45: dup 46: astore_2 47: astore 449: aload_3 50: pop 51: goto 10

Page 62: The bytecode hocus pocus - JavaOne 2016

@rrafols

AutoboxingLong total = 0;for(Integer i = 0; i < N; i++) { total += i;}

0: lconst_0 1: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;4: astore_1 5: iconst_0 6: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;9: astore_2 10: aload_2 11: invokevirtual #9 // Method java/lang/Integer.intValue:()I14: sipush N17: if_icmpge 5420: aload_1 21: invokevirtual #10 // Method java/lang/Long.longValue:()J24: aload_2 25: invokevirtual #9 // Method java/lang/Integer.intValue:()I28: i2l 29: ladd 30: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // Method java/lang/Integer.intValue:()I40: iconst_1 41: iadd 42: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;45: dup 46: astore_2 47: astore 449: aload_3 50: pop 51: goto 10

Page 63: The bytecode hocus pocus - JavaOne 2016

@rrafols

AutoboxingLong total = 0;for(Integer i = 0; i < N; i++) { total += i;}

0: lconst_0 1: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;4: astore_1 5: iconst_0 6: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;9: astore_2 10: aload_2 11: invokevirtual #9 // Method java/lang/Integer.intValue:()I14: sipush N17: if_icmpge 5420: aload_1 21: invokevirtual #10 // Method java/lang/Long.longValue:()J24: aload_2 25: invokevirtual #9 // Method java/lang/Integer.intValue:()I28: i2l 29: ladd 30: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // Method java/lang/Integer.intValue:()I40: iconst_1 41: iadd 42: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;45: dup 46: astore_2 47: astore 449: aload_3 50: pop 51: goto 10

Page 64: The bytecode hocus pocus - JavaOne 2016

@rrafols

AutoboxingLong total = 0;for(Integer i = 0; i < N; i++) { total += i;}

0: lconst_0 1: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;4: astore_1 5: iconst_0 6: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;9: astore_2 10: aload_2 11: invokevirtual #9 // Method java/lang/Integer.intValue:()I14: sipush N17: if_icmpge 5420: aload_1 21: invokevirtual #10 // Method java/lang/Long.longValue:()J24: aload_2 25: invokevirtual #9 // Method java/lang/Integer.intValue:()I28: i2l 29: ladd 30: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // Method java/lang/Integer.intValue:()I40: iconst_1 41: iadd 42: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;45: dup 46: astore_2 47: astore 449: aload_3 50: pop 51: goto 10

Page 65: The bytecode hocus pocus - JavaOne 2016

@rrafols

AutoboxingLong total = 0;for(Integer i = 0; i < N; i++) { total += i;}

0: lconst_0 1: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;4: astore_1 5: iconst_0 6: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;9: astore_2 10: aload_2 11: invokevirtual #9 // Method java/lang/Integer.intValue:()I14: sipush N17: if_icmpge 5420: aload_1 21: invokevirtual #10 // Method java/lang/Long.longValue:()J24: aload_2 25: invokevirtual #9 // Method java/lang/Integer.intValue:()I28: i2l 29: ladd 30: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // Method java/lang/Integer.intValue:()I40: iconst_1 41: iadd 42: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;45: dup 46: astore_2 47: astore 449: aload_3 50: pop 51: goto 10

Page 66: The bytecode hocus pocus - JavaOne 2016

@rrafols

AutoboxingLong total = 0;for(Integer i = 0; i < N; i++) { total += i;}

0: lconst_0 1: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;4: astore_1 5: iconst_0 6: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;9: astore_2 10: aload_2 11: invokevirtual #9 // Method java/lang/Integer.intValue:()I14: sipush N17: if_icmpge 5420: aload_1 21: invokevirtual #10 // Method java/lang/Long.longValue:()J24: aload_2 25: invokevirtual #9 // Method java/lang/Integer.intValue:()I28: i2l 29: ladd 30: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // Method java/lang/Integer.intValue:()I40: iconst_1 41: iadd 42: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;45: dup 46: astore_2 47: astore 449: aload_3 50: pop 51: goto 10

Page 67: The bytecode hocus pocus - JavaOne 2016

@rrafols

AutoboxingLong total = 0;for(Integer i = 0; i < N; i++) { total += i;}

0: lconst_0 1: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;4: astore_1 5: iconst_0 6: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;9: astore_2 10: aload_2 11: invokevirtual #9 // Method java/lang/Integer.intValue:()I14: sipush N17: if_icmpge 5420: aload_1 21: invokevirtual #10 // Method java/lang/Long.longValue:()J24: aload_2 25: invokevirtual #9 // Method java/lang/Integer.intValue:()I28: i2l 29: ladd 30: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // Method java/lang/Integer.intValue:()I40: iconst_1 41: iadd 42: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;45: dup 46: astore_2 47: astore 449: aload_3 50: pop 51: goto 10

Page 68: The bytecode hocus pocus - JavaOne 2016

@rrafols

AutoboxingLong total = 0;for(Integer i = 0; i < N; i++) { total += i;}

// ?

0: lconst_0 1: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;4: astore_1 5: iconst_0 6: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;9: astore_2 10: aload_2 11: invokevirtual #9 // Method java/lang/Integer.intValue:()I14: sipush N17: if_icmpge 5420: aload_1 21: invokevirtual #10 // Method java/lang/Long.longValue:()J24: aload_2 25: invokevirtual #9 // Method java/lang/Integer.intValue:()I28: i2l 29: ladd 30: invokestatic #7 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // Method java/lang/Integer.intValue:()I40: iconst_1 41: iadd 42: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;45: dup 46: astore_2 47: astore 449: aload_3 50: pop 51: goto 10

Page 69: The bytecode hocus pocus - JavaOne 2016

@rrafols

AutoboxingThis is what that code is actually doing:

Long total = Long.valueOf(0);for(Integer i = Integer.valueOf(0); i.intValue() < N; i = Integer.valueOf(i.intValue() + 1)) { total = Long.valueOf(total.longValue() + (long)i.intValue())}

Page 70: The bytecode hocus pocus - JavaOne 2016

@rrafols

AutoboxingObject creation

Long total = Long.valueOf(0);for(Integer i = Integer.valueOf(0); i.intValue() < N; i = Integer.valueOf(i.intValue() + 1)) { total = Long.valueOf(total.longValue() + (long)i.intValue())}

Page 71: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxing

What about Jack?

Page 72: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxing

Jack does not help in this situation

Page 73: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxing

What about the JIT compiler?

Page 74: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxing

Let's run that loop

10.000.000.000 times

(on my desktop computer)

Page 75: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxing

Page 76: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxing

Let's run that loop 100.000.000

Times on two Nexus 5

KitKat (Dalvik VM) & Lollipop (ART)

Page 77: The bytecode hocus pocus - JavaOne 2016

@rrafols

Autoboxing

Page 78: The bytecode hocus pocus - JavaOne 2016

@rrafols

Language Additions

Use them wisely!

Page 79: The bytecode hocus pocus - JavaOne 2016

@rrafols

Sorting

No bytecode mumbo-jumbo here

Page 80: The bytecode hocus pocus - JavaOne 2016

@rrafols

Let's sort some numbers…

Arrays.sort(...)

Page 81: The bytecode hocus pocus - JavaOne 2016

@rrafols

Difference between sorting primitive types & objects

Page 82: The bytecode hocus pocus - JavaOne 2016

@rrafols

Using int & Integer

Page 83: The bytecode hocus pocus - JavaOne 2016

@rrafols

Sorting objects is a stable sort

Default java algorithm: TimSort adaptation

Page 84: The bytecode hocus pocus - JavaOne 2016

@rrafols

Sorting primitives does not require to be stable sort

Default java algorithm:

Dual-Pivot quicksort

Page 85: The bytecode hocus pocus - JavaOne 2016

@rrafols

Sorting

Use primitive types as much as possible

Page 86: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops

Page 87: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops

What is going on behind the scenes

Page 88: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - ListArrayList<Integer> list = new …static long loopStandardList() {

long result = 0; for(int i = 0; i < list.size(); i++) {

result += list.get(i); }

return result;}

Page 89: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - ListArrayList<Integer> list = new …static long loopStandardList() {

long result = 0; for(int i = 0; i < list.size(); i++) {

result += list.get(i); }

return result;}

7: lload_0

8: getstatic #26 // Field list:Ljava/util/ArrayList;

11: iload_2

12: invokevirtual #54 // Method java/util/ArrayList.get:(I)

15: checkcast #38 // class java/lang/Integer

18: invokevirtual #58 // Method java/lang/Integer.intValue:()I

21: i2l

22: ladd

23: lstore_0

24: iinc 2, 1

27: iload_2

28: getstatic #26 // Field list:Ljava/util/ArrayList;

31: invokevirtual #61 // Method java/util/ArrayList.size:()I

34: if_icmplt 7

Page 90: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - ListArrayList<Integer> list = new …static long loopStandardList() {

long result = 0; for(int i = 0; i < list.size(); i++) {

result += list.get(i); }

return result;}

7: lload_0

8: getstatic #26 // Field list:Ljava/util/ArrayList;

11: iload_2

12: invokevirtual #54 // Method java/util/ArrayList.get:(I)

15: checkcast #38 // class java/lang/Integer

18: invokevirtual #58 // Method java/lang/Integer.intValue:()I

21: i2l

22: ladd

23: lstore_0

24: iinc 2, 1

27: iload_2

28: getstatic #26 // Field list:Ljava/util/ArrayList;

31: invokevirtual #61 // Method java/util/ArrayList.size:()I

34: if_icmplt 7

Page 91: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - ListArrayList<Integer> list = new …static long loopStandardList() {

long result = 0; for(int i = 0; i < list.size(); i++) {

result += list.get(i); }

return result;}

7: lload_0

8: getstatic #26 // Field list:Ljava/util/ArrayList;

11: iload_2

12: invokevirtual #54 // Method java/util/ArrayList.get:(I)

15: checkcast #38 // class java/lang/Integer

18: invokevirtual #58 // Method java/lang/Integer.intValue:()I

21: i2l

22: ladd

23: lstore_0

24: iinc 2, 1

27: iload_2

28: getstatic #26 // Field list:Ljava/util/ArrayList;

31: invokevirtual #61 // Method java/util/ArrayList.size:()I

34: if_icmplt 7

Page 92: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - ListArrayList<Integer> list = new …static long loopStandardList() {

long result = 0; for(int i = 0; i < list.size(); i++) {

result += list.get(i); }

return result;}

7: lload_0

8: getstatic #26 // Field list:Ljava/util/ArrayList;

11: iload_2

12: invokevirtual #54 // Method java/util/ArrayList.get:(I)

15: checkcast #38 // class java/lang/Integer

18: invokevirtual #58 // Method java/lang/Integer.intValue:()I

21: i2l

22: ladd

23: lstore_0

24: iinc 2, 1

27: iload_2

28: getstatic #26 // Field list:Ljava/util/ArrayList;

31: invokevirtual #61 // Method java/util/ArrayList.size:()I

34: if_icmplt 7

Page 93: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - foreachArrayList<Integer> list = new …static long loopForeachList() {

long result = 0; for(int v : list) {

result += v; } return result;

}

Page 94: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - foreachArrayList<Integer> list = new …static long loopForeachList() {

long result = 0; for(int v : list) {

result += v; } return result;

}

12: aload_3

13: invokeinterface #70, 1 // java/util/Iterator.next:()

18: checkcast #38 // class java/lang/Integer

21: invokevirtual #58 // Method java/lang/Integer.intValue:()I

24: istore_2

25: lload_0

26: iload_2

27: i2l

28: ladd

29: lstore_0

30: aload_3

31: invokeinterface #76, 1 // java/util/Iterator.hasNext:()Z

36: ifne 12

Page 95: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - foreachArrayList<Integer> list = new …static long loopForeachList() {

long result = 0; for(int v : list) {

result += v; } return result;

}

12: aload_3

13: invokeinterface #70, 1 // java/util/Iterator.next:()

18: checkcast #38 // class java/lang/Integer

21: invokevirtual #58 // Method java/lang/Integer.intValue:()I

24: istore_2

25: lload_0

26: iload_2

27: i2l

28: ladd

29: lstore_0

30: aload_3

31: invokeinterface #76, 1 // java/util/Iterator.hasNext:()Z

36: ifne 12

Page 96: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - foreachArrayList<Integer> list = new …static long loopForeachList() {

long result = 0; for(int v : list) {

result += v; } return result;

}

12: aload_3

13: invokeinterface #70, 1 // java/util/Iterator.next:()

18: checkcast #38 // class java/lang/Integer

21: invokevirtual #58 // Method java/lang/Integer.intValue:()I

24: istore_2

25: lload_0

26: iload_2

27: i2l

28: ladd

29: lstore_0

30: aload_3

31: invokeinterface #76, 1 // java/util/Iterator.hasNext:()Z

36: ifne 12

Page 97: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - Arraystatic int[] array = new ...static long loopStandardArray() {

long result = 0; for(int i = 0; i < array.length; i++) {

result += array[i]; } return result;

}

Page 98: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - Arraystatic int[] array = new ...static long loopStandardArray() {

long result = 0; for(int i = 0; i < array.length; i++) {

result += array[i]; } return result;

}

7: lload_0

8: getstatic #28 // Field array:[I

11: iload_2

12: iaload

13: i2l

14: ladd

15: lstore_0

16: iinc 2, 1

19: iload_2

20: getstatic #28 // Field array:[I

23: arraylength

24: if_icmplt 7

Page 99: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - Arraystatic int[] array = new ...static long loopStandardArray() {

long result = 0; for(int i = 0; i < array.length; i++) {

result += array[i]; } return result;

}

7: lload_0 8: getstatic #28 // Field array:[I11: iload_2 12: iaload 13: i2l 14: ladd 15: lstore_0 16: iinc 2, 1

19: iload_2

20: getstatic #28 // Field array:[I

23: arraylength

24: if_icmplt 7

Page 100: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - Arraystatic int[] array = new ...static long loopStandardArray() {

long result = 0; for(int i = 0; i < array.length; i++) {

result += array[i]; } return result;

}

7: lload_0 8: getstatic #28 // Field array:[I

11: iload_2

12: iaload

13: i2l

14: ladd

15: lstore_0

16: iinc 2, 1

19: iload_2 20: getstatic #28 // Field array:[I23: arraylength 24: if_icmplt 7

Page 101: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - size cachedstatic int[] array = new ...static long loopStandardArray () {

long result = 0; int length = array.length;

for(int i = 0; i < length; i++) { result += array[i];

} return result;

}

Page 102: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - size cachedstatic int[] array = new ...static long loopStandardArray () {

long result = 0; int length = array.length;

for(int i = 0; i < length; i++) { result += array[i];

} return result;

}

12: lload_0

13: getstatic #28 // Field array:[I

16: iload_3

17: iaload

18: i2l

19: ladd

20: lstore_0

21: iinc 3, 1

24: iload_3

25: iload_2

26: if_icmplt 12

Page 103: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - size cachedstatic int[] array = new ...static long loopStandardArray () {

long result = 0; int length = array.length;

for(int i = 0; i < length; i++) { result += array[i];

} return result;

}

12: lload_0

13: getstatic #28 // Field array:[I

16: iload_3

17: iaload

18: i2l

19: ladd

20: lstore_0

21: iinc 3, 1

24: iload_3 25: iload_2 26: if_icmplt 12

Page 104: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - backwardsstatic int[] array = new ...static long loopStandardArray () {

long result = 0;for(int i = array.length - 1; i >= 0; i--) {

result += array[i];}return result;

}

Page 105: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - backwardsstatic int[] array = new ...static long loopStandardArray () {

long result = 0;for(int i = array.length - 1; i >= 0; i--) {

result += array[i];}return result;

}

12: lload_0

13: getstatic #28 // Field array:[I

16: iload_2

17: iaload

18: i2l

19: ladd

20: lstore_0

21: iinc 2, -1

24: iload_2

25: ifge 12

Page 106: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops - backwardsstatic int[] array = new ...static long loopStandardArray () {

long result = 0;for(int i = array.length - 1; i >= 0; i--) {

result += array[i];}return result;

}

12: lload_0 13: getstatic #28 // Field array:[I

16: iload_2

17: iaload

18: i2l

19: ladd

20: lstore_0

21: iinc 2, -1

24: iload_2 25: ifge 12

Page 107: The bytecode hocus pocus - JavaOne 2016

@rrafols

Page 108: The bytecode hocus pocus - JavaOne 2016

@rrafols

Page 109: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops – foreach IIstatic long loopForeachArray(int[] array) {

long result = 0; for(int v : array) {

result += v; } return result;

}

Page 110: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops – foreach IIstatic long loopForeachArray(int[] array) {

long result = 0; for(int v : array) {

result += v; } return result;

}

 0: lconst_0 1: lstore_1 2: aload_0 3: dup 4: astore        6 6: arraylength 7: istore        5 9: iconst_010: istore        412: goto          2915: aload         617: iload         419: iaload20: istore_321: lload_122: iload_323: i2l24: ladd25: lstore_126: iinc          4, 129: iload         431: iload         533: if_icmplt     15

0 array 4 -

1 - 5 -

2 - 6 -

3 - 7 -

Page 111: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops – foreach IIstatic long loopForeachArray(int[] array) {

long result = 0; for(int v : array) {

result += v; } return result;

}

 0: lconst_0 1: lstore_1 2: aload_0 3: dup 4: astore        6 6: arraylength 7: istore        5 9: iconst_010: istore        412: goto          2915: aload         617: iload         419: iaload20: istore_321: lload_122: iload_323: i2l24: ladd25: lstore_126: iinc          4, 129: iload         431: iload         533: if_icmplt     15

0 array 4 -

1 0 (result) 5 -

2 - 6 -

3 - 7 -

Page 112: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops – foreach IIstatic long loopForeachArray(int[] array) {

long result = 0; for(int v : array) {

result += v; } return result;

}

 0: lconst_0 1: lstore_1 2: aload_0 3: dup 4: astore        6 6: arraylength 7: istore        5 9: iconst_010: istore        412: goto          2915: aload         617: iload         419: iaload20: istore_321: lload_122: iload_323: i2l24: ladd25: lstore_126: iinc          4, 129: iload         431: iload         533: if_icmplt     15

0 array 4 -

1 0 (result) 5 -

2 - 6 array

3 - 7 -

Page 113: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops – foreach IIstatic long loopForeachArray(int[] array) {

long result = 0; for(int v : array) {

result += v; } return result;

}

 0: lconst_0 1: lstore_1 2: aload_0 3: dup 4: astore        6 6: arraylength 7: istore        5 9: iconst_010: istore        412: goto          2915: aload         617: iload         419: iaload20: istore_321: lload_122: iload_323: i2l24: ladd25: lstore_126: iinc          4, 129: iload         431: iload         533: if_icmplt     15

0 array 4 -

1 0 (result) 5 array.length

2 - 6 array

3 - 7 -

Page 114: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops – foreach IIstatic long loopForeachArray(int[] array) {

long result = 0; for(int v : array) {

result += v; } return result;

}

 0: lconst_0 1: lstore_1 2: aload_0 3: dup 4: astore        6 6: arraylength 7: istore        5 9: iconst_010: istore        412: goto          2915: aload         617: iload         419: iaload20: istore_321: lload_122: iload_323: i2l24: ladd25: lstore_126: iinc          4, 129: iload         431: iload         533: if_icmplt     15

0 array 4 0 (loop index)

1 0 (result) 5 array.length

2 - 6 array

3 - 7 -

Page 115: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops – foreach IIstatic long loopForeachArray(int[] array) {

long result = 0; for(int v : array) {

result += v; } return result;

}

 0: lconst_0 1: lstore_1 2: aload_0 3: dup 4: astore        6 6: arraylength 7: istore        5 9: iconst_010: istore        412: goto          2915: aload         617: iload         419: iaload20: istore_321: lload_122: iload_323: i2l24: ladd25: lstore_126: iinc          4, 129: iload         431: iload         533: if_icmplt     15

0 array 4 0 (loop index)

1 0 (result) 5 array.length

2 - 6 array

3 - 7 -

Page 116: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops – foreach IIstatic long loopForeachArray(int[] array) {

long result = 0; for(int v : array) {

result += v; } return result;

}

 0: lconst_0 1: lstore_1 2: aload_0 3: dup 4: astore        6 6: arraylength 7: istore        5 9: iconst_010: istore        412: goto          2915: aload         617: iload         419: iaload20: istore_321: lload_122: iload_323: i2l24: ladd25: lstore_126: iinc          4, 129: iload         431: iload         533: if_icmplt     15

0 array 4 0 (loop index)

1 0 (result) 5 array.length

2 - 6 array

3 array[index] 7 -

Page 117: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops – foreach IIstatic long loopForeachArray(int[] array) {

long result = 0; for(int v : array) {

result += v; } return result;

}

 0: lconst_0 1: lstore_1 2: aload_0 3: dup 4: astore        6 6: arraylength 7: istore        5 9: iconst_010: istore        412: goto          2915: aload         617: iload         419: iaload20: istore_321: lload_122: iload_323: i2l24: ladd25: lstore_126: iinc          4, 129: iload         431: iload         533: if_icmplt     15

0 array 4 0 (loop index)

1 0 + array[index] 5 array.length

2 - 6 array

3 array[index] 7 -

Page 118: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops – foreach IIstatic long loopForeachArray(int[] array) {

long result = 0; for(int v : array) {

result += v; } return result;

}

 0: lconst_0 1: lstore_1 2: aload_0 3: dup 4: astore        6 6: arraylength 7: istore        5 9: iconst_010: istore        412: goto          2915: aload         617: iload         419: iaload20: istore_321: lload_122: iload_323: i2l24: ladd25: lstore_126: iinc          4, 129: iload         431: iload         533: if_icmplt     15

0 array 4 0 (loop index) + 1

1 0 + array[index] 5 array.length

2 - 6 array

3 array[index] 7 -

Page 119: The bytecode hocus pocus - JavaOne 2016

@rrafols

Page 120: The bytecode hocus pocus - JavaOne 2016

@rrafols

Page 121: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops

Use arrays instead of lists

Page 122: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops

When using lists, avoid foreach or iterator constructions if

performance is a requirement

Page 123: The bytecode hocus pocus - JavaOne 2016

@rrafols

Manual bytecode optimization

Worth it?

Page 124: The bytecode hocus pocus - JavaOne 2016

@rrafols

Loops – foreach II  0: lconst_0 1: lstore_1 2: aload_0 3: dup 4: astore        6 6: arraylength 7: istore        5 9: iconst_010: istore        412: goto          2915: aload         617: iload         419: iaload20: istore_321: lload_122: iload_323: i2l24: ladd25: lstore_126: iinc          4, 129: iload         431: iload         533: if_icmplt     15

0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_010: iload_111: iaload12: i2l13: ladd14: iinc 1, 117: iload_118: iload_319: if_icmplt 9

Manual bytecode optimization

Page 125: The bytecode hocus pocus - JavaOne 2016

@rrafols

Manual bytecode optimization 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_010: iload_111: iaload12: i2l13: ladd14: iinc 1, 117: iload_118: iload_319: if_icmplt 9

Local variables

0 array 3 -

1 - 4 -

2 - 5 -

Stack

-

-

-

Page 126: The bytecode hocus pocus - JavaOne 2016

@rrafols

Manual bytecode optimization 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_010: iload_111: iaload12: i2l13: ladd14: iinc 1, 117: iload_118: iload_319: if_icmplt 9

Local variables

0 array 3 array.length

1 - 4 -

2 - 5 -

Stack

-

-

-

Page 127: The bytecode hocus pocus - JavaOne 2016

@rrafols

Manual bytecode optimization 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_010: iload_111: iaload12: i2l13: ladd14: iinc 1, 117: iload_118: iload_319: if_icmplt 9

Local variables

0 array 3 array.length

1 0 (index) 4 -

2 - 5 -

Stack

-

-

-

Page 128: The bytecode hocus pocus - JavaOne 2016

@rrafols

Manual bytecode optimization 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_010: iload_111: iaload12: i2l13: ladd14: iinc 1, 117: iload_118: iload_319: if_icmplt 9

Local variables

0 array 3 array.length

1 0 (index) 4 -

2 - 5 -

Stack

0 (result)

-

-

Page 129: The bytecode hocus pocus - JavaOne 2016

@rrafols

Manual bytecode optimization 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_010: iload_111: iaload12: i2l13: ladd14: iinc 1, 117: iload_118: iload_319: if_icmplt 9

Local variables

0 array 3 array.length

1 0 (index) 4 -

2 - 5 -

Stack

0 (result)

array[index]

-

Page 130: The bytecode hocus pocus - JavaOne 2016

@rrafols

Manual bytecode optimization 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_010: iload_111: iaload12: i2l13: ladd14: iinc 1, 117: iload_118: iload_319: if_icmplt 9

Local variables

0 array 3 array.length

1 0 (index) 4 -

2 - 5 -

Stack

0 + array[index]

-

-

Page 131: The bytecode hocus pocus - JavaOne 2016

@rrafols

Manual bytecode optimization 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_010: iload_111: iaload12: i2l13: ladd14: iinc 1, 117: iload_118: iload_319: if_icmplt 9

Local variables

0 array 3 array.length

1 0 (index) + 1 4 -

2 - 5 -

Stack

0 + array[index]

-

-

Page 132: The bytecode hocus pocus - JavaOne 2016

@rrafols *reduced data set

Page 133: The bytecode hocus pocus - JavaOne 2016

@rrafols

Worth it?

Only in very specific, unique, peculiar cases.

Too much effort involved.

Page 134: The bytecode hocus pocus - JavaOne 2016

@rrafols

Calling a method

Is there an overhead?

Page 135: The bytecode hocus pocus - JavaOne 2016

@rrafols

Overhead of calling a methodfor(int i = 0; i < N; i++) {

setVal(getVal() + 1);

}

for(int i = 0; i < N; i++) {

val = val + 1;

}

vs

Page 136: The bytecode hocus pocus - JavaOne 2016

@rrafols

Page 137: The bytecode hocus pocus - JavaOne 2016

@rrafols

String concatenation

The evil + sign

Page 138: The bytecode hocus pocus - JavaOne 2016

@rrafols

String concatenationString str = "";for(int i = 0; i < N; i++) {

str += OTHER_STR;}

Page 139: The bytecode hocus pocus - JavaOne 2016

@rrafols

String concatenationString str = "";for(int i = 0; i < N; i++) {

str += OTHER_STR;}

0: ldc #13 // String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: sipush N9: if_icmpge 4012: new #14 // class java/lang/StringBuilder15: dup 16: invokespecial #15 // Method java/lang/StringBuilder."<init>":()V19: aload_1 20: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)23: aload_0 24: getfield #3 // Field OTHER_STR:Ljava/lang/String;27: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)30: invokevirtual #17 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;33: astore_1 34: iinc 2, 137: goto 5

Page 140: The bytecode hocus pocus - JavaOne 2016

@rrafols

String concatenationString str = "";for(int i = 0; i < N; i++) {

str += OTHER_STR;}

0: ldc #13 // String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: sipush N9: if_icmpge 4012: new #14 // class java/lang/StringBuilder15: dup 16: invokespecial #15 // Method java/lang/StringBuilder."<init>":()V19: aload_1 20: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)23: aload_0 24: getfield #3 // Field OTHER_STR:Ljava/lang/String;27: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)30: invokevirtual #17 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;33: astore_1 34: iinc 2, 137: goto 5

Page 141: The bytecode hocus pocus - JavaOne 2016

@rrafols

String concatenationString str = "";for(int i = 0; i < N; i++) {

str += OTHER_STR;}

0: ldc #13 // String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: sipush N9: if_icmpge 4012: new #14 // class java/lang/StringBuilder15: dup 16: invokespecial #15 // Method java/lang/StringBuilder."<init>":()V19: aload_1 20: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)23: aload_0 24: getfield #3 // Field OTHER_STR:Ljava/lang/String;27: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)30: invokevirtual #17 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;33: astore_1 34: iinc 2, 137: goto 5

Page 142: The bytecode hocus pocus - JavaOne 2016

@rrafols

String concatenationString str = "";for(int i = 0; i < N; i++) {

str += OTHER_STR;}

0: ldc #13 // String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: sipush N9: if_icmpge 4012: new #14 // class java/lang/StringBuilder15: dup 16: invokespecial #15 // Method java/lang/StringBuilder."<init>":()V19: aload_1 20: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)23: aload_0 24: getfield #3 // Field OTHER_STR:Ljava/lang/String;27: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)30: invokevirtual #17 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;33: astore_1 34: iinc 2, 137: goto 5

Page 143: The bytecode hocus pocus - JavaOne 2016

@rrafols

String concatenationString str = "";for(int i = 0; i < N; i++) {

str += OTHER_STR;}

0: ldc #13 // String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: sipush N9: if_icmpge 4012: new #14 // class java/lang/StringBuilder15: dup 16: invokespecial #15 // Method java/lang/StringBuilder."<init>":()V19: aload_1 20: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)23: aload_0 24: getfield #3 // Field OTHER_STR:Ljava/lang/String;27: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)30: invokevirtual #17 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;33: astore_1 34: iinc 2, 137: goto 5

Page 144: The bytecode hocus pocus - JavaOne 2016

@rrafols

String concatenationString str = "";for(int i = 0; i < N; i++) {

str += OTHER_STR;}

0: ldc #13 // String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: sipush N9: if_icmpge 4012: new #14 // class java/lang/StringBuilder15: dup 16: invokespecial #15 // Method java/lang/StringBuilder."<init>":()V19: aload_1 20: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)23: aload_0 24: getfield #3 // Field OTHER_STR:Ljava/lang/String;27: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)30: invokevirtual #17 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;33: astore_1 34: iinc 2, 137: goto 5

Page 145: The bytecode hocus pocus - JavaOne 2016

@rrafols

String concatenation - equivalent String str = "";for(int i = 0; i < N; i++) { StringBuilder sb = new StringBuilder(); sb.append(str); sb.append(OTHER_STR); str = sb.toString();}

Page 146: The bytecode hocus pocus - JavaOne 2016

@rrafols

String concatenationObject creation:

String str = "";for(int i = 0; i < N; i++) { StringBuilder sb = new StringBuilder(); sb.append(str); sb.append(OTHER_STR); str = sb.toString();}

Page 147: The bytecode hocus pocus - JavaOne 2016

@rrafols

String concatenation

alternatives

Page 148: The bytecode hocus pocus - JavaOne 2016

@rrafols

String.concat()• Concat cost is O(N) + O(M)

• Concat returns a new String Object.

String str = "";for(int i = 0; i < N; i++) {

str = str.concat(OTHER_STR);}

Page 149: The bytecode hocus pocus - JavaOne 2016

@rrafols

String.concat()Object creation:

String str = "";for(int i = 0; i < N; i++) {

str = str.concat(OTHER_STR);}

Page 150: The bytecode hocus pocus - JavaOne 2016

@rrafols

StringBuilder• StringBuilder.append cost is O(M) [M being the length of

appended String]

StringBuilder sb = new StringBuilder()for(int i = 0; i < N; i++) { sb.append(OTHER_STR);}str = sb.toString();

Page 151: The bytecode hocus pocus - JavaOne 2016

@rrafols

StringBuilderStringBuilder sb = new StringBuilder()for(int i = 0; i < N; i++) { sb.append(OTHER_STR);}str = sb.toString();

0: ldc #13 // String 2: astore_1 3: new #14 // class java/lang/StringBuilder6: dup 7: invokespecial #15 // Method java/lang/StringBuilder."<init>":()V10: astore_2 11: iconst_0 12: istore_3 13: iload_3 14: sipush N17: if_icmpge 3520: aload_2 21: aload_0 22: getfield #3 // Field OTHER_STR:Ljava/lang/String;25: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;28: pop 29: iinc 3, 132: goto 13

Page 152: The bytecode hocus pocus - JavaOne 2016

@rrafols

StringBuilderStringBuilder sb = new StringBuilder()for(int i = 0; i < N; i++) { sb.append(OTHER_STR);}str = sb.toString();

0: ldc #13 // String 2: astore_1 3: new #14 // class java/lang/StringBuilder6: dup 7: invokespecial #15 // Method java/lang/StringBuilder."<init>":()V10: astore_2 11: iconst_0 12: istore_3 13: iload_3 14: sipush N17: if_icmpge 3520: aload_2 21: aload_0 22: getfield #3 // Field OTHER_STR:Ljava/lang/String;25: invokevirtual #16 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;28: pop 29: iinc 3, 132: goto 13

Page 153: The bytecode hocus pocus - JavaOne 2016

@rrafols

StringBuilderObject creation:

StringBuilder sb = new StringBuilder();for(int i = 0; i < N; i++) { sb.append(OTHER_STR);}str = sb.toString();

Page 154: The bytecode hocus pocus - JavaOne 2016

@rrafols

String concatenation

Use StringBuilder (properly) as much as possible. StringBuffer is the thread safe implementation.

Page 155: The bytecode hocus pocus - JavaOne 2016

@rrafols

Strings in case statements

Page 156: The bytecode hocus pocus - JavaOne 2016

@rrafols

public void taskStateMachine(String status) { switch(status) { case "PENDING": System.out.println("Status pending"); break;

case "EXECUTING": System.out.println("Status executing"); break; } }

Page 157: The bytecode hocus pocus - JavaOne 2016

@rrafols

Page 158: The bytecode hocus pocus - JavaOne 2016

@rrafols

Page 159: The bytecode hocus pocus - JavaOne 2016

@rrafols

Tooling

Page 160: The bytecode hocus pocus - JavaOne 2016

@rrafols

Tooling - DisassemblerJava• javap -c <classfile>

Android:•Dexdump -d <dexfile>

Page 161: The bytecode hocus pocus - JavaOne 2016

@rrafols

Tooling - AssemblerKrakatauhttps://github.com/Storyyeller/Krakatau

Page 162: The bytecode hocus pocus - JavaOne 2016

@rrafols

Tooling – Disassembler - ARTadb pull /data/dalvik-cache/arm/data@app@<package>-1@base [email protected]

gobjdump -D <file>

Page 163: The bytecode hocus pocus - JavaOne 2016

@rrafols

Tooling – Disassembler - ART

adb shell oatdump --oat-file=/data/dalvik-cache/arm/data@app@<package>[email protected]@classes.dex

Page 164: The bytecode hocus pocus - JavaOne 2016

@rrafols

Tooling – PrintAssembly - JIT-XX:+UnlockDiagnosticVMOptions

-XX:+PrintAssembly

-XX:CompileCommand=print,com.raimon.test.Test::method

Under the Hood of the JVM: From Bytecode Through the JIT to Assembly [CON3808]

http://alblue.bandlem.com/2016/09/javaone-hotspot.html

Page 165: The bytecode hocus pocus - JavaOne 2016

@rrafols

Always measure

example - yuv2rgb optimization

Page 166: The bytecode hocus pocus - JavaOne 2016

@rrafols

Source: Wikipedia

Page 167: The bytecode hocus pocus - JavaOne 2016

@rrafols

Page 168: The bytecode hocus pocus - JavaOne 2016

@rrafols

Slightly optimized version

precalc tables, fixed point operations, 2 pixels per loop…

Page 169: The bytecode hocus pocus - JavaOne 2016

@rrafols

Page 170: The bytecode hocus pocus - JavaOne 2016

@rrafols

Page 171: The bytecode hocus pocus - JavaOne 2016

@rrafols

Lets compare:

Normal, minified, minified with optimizations & jack

Minified = obfuscated using Proguard

Page 172: The bytecode hocus pocus - JavaOne 2016

@rrafols

Normal Minified Minified & optimized Jack0

2000

4000

6000

8000

10000

12000

14000

16000

18000

20000

non-optimizedoptimized

Page 173: The bytecode hocus pocus - JavaOne 2016

@rrafols

Performance measurements

Avoid doing multiple tests in one run

JIT might be evil!

Page 174: The bytecode hocus pocus - JavaOne 2016

@rrafols

Thank you!

http://blog.rafols.org

@rrafols

https://es.linkedin.com/in/raimonrafols