SlideShare a Scribd company logo
1 of 178
Download to read offline
the bytecode
gobbledygook
#perfmatters
@rrafols
Disclaimer:
This presentation contains
bytecode
Content is my own experimentation and
might differ on other environments
Competitions
Work
2015 Local winner
2016+ Ambassador
2016 Runner up
2018 Honorable mention
Demoscene
Speaker
Author Entrepreneurship
@rrafols
Everything starts with our
friend the java compiler.
*.java → [javac] → *.class
Or on Android
*.java → [javac] → *.class
*.class → [dx] → dex file
*.java → [javac] → *.class
*.class → [dx] → dex
dex → [dexopt] → opt. dex
dex → [dex2oat] → native
but change is coming!
Jack & Jill
but change is coming!
Jack & Jill
*.java → [jack] → dex file
but change is still coming!
D8 & R8
*.java → [javac] → *.class
*.class → [d8/r8] → dex file
Let’s focus first on javac
Javac vs other compilers
Compilers
Produces optimized code
for the target platform
javac
Does not produce
optimized code*
javac
Does not know on which
architecture the code will
be executed
Source: Oracle
For this reason
Java bytecode &
operations are stack
based
Easy to interpret
But not the most
performant solution
Quick example
Stack based integer
addition
j = j + i
Java bytecode
iload_3
iload_2
iadd
istore_2
Register based approach
add r01, r02, r01
or
add eax, ebx
Let’s make things
interesting…
j = j + i + k + w + h * 2 + p * p;
Java bytecode
0: iload_2
1: iload_1
2: iadd
3: iload_3
4: iadd
5: iload 4
7: iadd
8: iload 5
10: iconst_2
11: imul
12: iadd
13: iload 6
15: iload 6
17: imul
18: iadd
19: istore_2
j = j + i + k + w + h * 2 + p * p;
Local vars
1: i
2: j
3: k
4: w
5: h
6: p
0: iload_2
1: iload_1
2: iadd
3: iload_3
4: iadd
5: iload 4
7: iadd
8: iload 5
10: iconst_2
11: imul
12: iadd
13: iload 6
15: iload 6
17: imul
18: iadd
19: istore_2
j = j + i + k + w + h * 2 + p * p;
Local vars
1: i
2: j
3: k
4: w
5: h
6: p
0: iload_2
1: iload_1
2: iadd
3: iload_3
4: iadd
5: iload 4
7: iadd
8: iload 5
10: iconst_2
11: imul
12: iadd
13: iload 6
15: iload 6
17: imul
18: iadd
19: istore_2
j = j + i + k + w + h * 2 + p * p;
Local vars
1: i
2: j
3: k
4: w
5: h
6: p
0: iload_2
1: iload_1
2: iadd
3: iload_3
4: iadd
5: iload 4
7: iadd
8: iload 5
10: iconst_2
11: imul
12: iadd
13: iload 6
15: iload 6
17: imul
18: iadd
19: istore_2
j = j + i + k + w + h * 2 + p * p;
Local vars
1: i
2: j
3: k
4: w
5: h
6: p
0: iload_2
1: iload_1
2: iadd
3: iload_3
4: iadd
5: iload 4
7: iadd
8: iload 5
10: iconst_2
11: imul
12: iadd
13: iload 6
15: iload 6
17: imul
18: iadd
19: istore_2
j = j + i + k + w + h * 2 + p * p;
Local vars
1: i
2: j
3: k
4: w
5: h
6: p
0: iload_2
1: iload_1
2: iadd
3: iload_3
4: iadd
5: iload 4
7: iadd
8: iload 5
10: iconst_2
11: imul
12: iadd
13: iload 6
15: iload 6
17: imul
18: iadd
19: istore_2
j = j + i + k + w + h * 2 + p * p;
Local vars
1: i
2: j
3: k
4: w
5: h
6: p
0: iload_2
1: iload_1
2: iadd
3: iload_3
4: iadd
5: iload 4
7: iadd
8: iload 5
10: iconst_2
11: imul
12: iadd
13: iload 6
15: iload 6
17: imul
18: iadd
19: istore_2
j = j + i + k + w + h * 2 + p * p;
Local vars
1: i
2: j
3: k
4: w
5: h
6: p
Register based approach
add r01, r02, r01
add r01, r03, r01
add r01, r04, r01
mul r07, r05, #2
add r01, r07, r01
mul r08, r06, r06
add r02, r08, r01
j = j + i + k + w + h * 2 + p * p;
r01: i
r02: j
r03: k
r04: w
r05: h
r06: p
Java VM (JVM)
Only the JVM knows the
architecture where is running.
In our previous example, we used up to
8 registers, but some CPUs might have
less than 8 registers…
Java VM (JVM)
All optimizations are left to
be done by the JVM
Maybe takes this concept
a bit too far...
Imagine this simple C code
#include <stdio.h>
int main() {
int a = 10;
int b = 1 + 2 + 3 + 4 + 5 + 6 + a;
printf("%dn", b);
}
GCC compiler
#include <stdio.h>
int main() {
int a = 10;
int b = 1 + 2 + 3 + 4 + 5 + 6 + a;
printf("%dn", b);
}
…
movl $31, %esi
call _printf
…
* Using gcc & -O2 compiler option
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
...
Let's do a small change
#include <stdio.h>
int main() {
int a = 10;
int b = 1 + 2 + 3 + 4 + 5 + a + 6;
printf("%dn", b);
}
GCC compiler
#include <stdio.h>
int main() {
int a = 10;
int b = 1 + 2 + 3 + 4 + 5 + a + 6;
printf("%dn", b);
}
…
movl $31, %esi
call _printf
…
* Using gcc & -O2 compiler option
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 15
5: iload_1
6: iadd
7: bipush 6
9: iadd
10: istore_2
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);
}
javac
00: bipush 10
02: istore_1
03: iload_1
04: iconst_1
05: iadd
06: iconst_2
07: iadd
08: iconst_3
09: iadd
10: iconst_4
11: iadd
12: iconst_5
13: iadd
14: bipush 6
16: iadd
17: istore_2
public static void main(String args[]) {
int a = 10;
int b = a + 1 + 2 + 3 + 4 + 5 + 6;
System.out.println(b);
}
On Android there was
jack to the rescue...
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 31
2: sget-object v1,
Ljava/lang/System;
4: invoke-virtual {v1, v0}
7: return-void
...
but d8 does the
job as well...
d8
public static void main(String args[]) {
int a = 10;
int b = a + 1 + 2 + 3 + 4 + 5 + 6;
System.out.println(b);
}
...
0: sget-object v1,
Ljava/lang/System;…
2: const/16 v0, #int 31
4: invoke-virtual {v1, v0}
7: return-void
...
And on Java there is the
JIT compiler to the rescue
JIT assembly output
public static void main(String args[]) {
int a = 10;
int b = a + 1 + 2 + 3 + 4 + 5 + 6;
System.out.println(b);
}
...
0x00000001104b2bff: mov eax, 0x0001f
...
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
Language additions
Thinks to consider
Autoboxing
Transparent to the developer
but compiler adds some
'extra' code
Autoboxing
long 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 21
10: lload_1
11: iload_3
12: i2l
13: ladd
14: lstore_1
15: iinc 3, 1
18: goto 4
Autoboxing
long 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 21
10: lload_1
11: iload_3
12: i2l
13: ladd
14: lstore_1
15: iinc 3, 1
18: goto 4
Autoboxing
long 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 21
10: lload_1
11: iload_3
12: i2l
13: ladd
14: lstore_1
15: iinc 3, 1
18: goto 4
Autoboxing
long 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 21
10: lload_1
11: iload_3
12: i2l
13: ladd
14: lstore_1
15: iinc 3, 1
18: goto 4
21:
Autoboxing
long 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 21
10: lload_1
11: iload_3
12: i2l
13: ladd
14: lstore_1
15: iinc 3, 1
18: goto 4
Autoboxing
long 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 21
10: lload_1
11: iload_3
12: i2l
13: ladd
14: lstore_1
15: iinc 3, 1
18: goto 4
Autoboxing
long 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 21
10: lload_1
11: iload_3
12: i2l
13: ladd
14: lstore_1
15: iinc 3, 1
18: goto 4
Autoboxing
Long total = 0;
for(Integer i = 0; i < N; i++) {
total += i;
}
Autoboxing
Long total = 0;
for(Integer i = 0; i < N; i++) {
total += i;
}
00: lconst_0
01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
04: astore_1
05: iconst_0
06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
09: astore_2
10: aload_2
11: invokevirtual #9 // java/lang/Integer.intValue:()I
14: sipush N
17: if_icmpge 54
20: aload_1
21: invokevirtual #10 // java/lang/Long.longValue:()J
24: aload_2
25: invokevirtual #9 // java/lang/Integer.intValue:()I
28: i2l
29: ladd
30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
33: astore_1
34: aload_2
35: astore_3
36: aload_2
37: invokevirtual #9 // java/lang/Integer.intValue:()I
40: iconst_1
41: iadd
42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
45: dup
46: astore_2
47: astore 4
49: aload_3
50: pop
51: goto 10
Autoboxing
Long total = 0;
for(Integer i = 0; i < N; i++) {
total += i;
}
00: lconst_0
01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
04: astore_1
05: iconst_0
06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
09: astore_2
10: aload_2
11: invokevirtual #9 // java/lang/Integer.intValue:()I
14: sipush N
17: if_icmpge 54
20: aload_1
21: invokevirtual #10 // java/lang/Long.longValue:()J
24: aload_2
25: invokevirtual #9 // java/lang/Integer.intValue:()I
28: i2l
29: ladd
30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
33: astore_1
34: aload_2
35: astore_3
36: aload_2
37: invokevirtual #9 // java/lang/Integer.intValue:()I
40: iconst_1
41: iadd
42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
45: dup
46: astore_2
47: astore 4
49: aload_3
50: pop
51: goto 10
Autoboxing
Long total = 0;
for(Integer i = 0; i < N; i++) {
total += i;
}
00: lconst_0
01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
04: astore_1
05: iconst_0
06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
09: astore_2
10: aload_2
11: invokevirtual #9 // java/lang/Integer.intValue:()I
14: sipush N
17: if_icmpge 54
20: aload_1
21: invokevirtual #10 // java/lang/Long.longValue:()J
24: aload_2
25: invokevirtual #9 // java/lang/Integer.intValue:()I
28: i2l
29: ladd
30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
33: astore_1
34: aload_2
35: astore_3
36: aload_2
37: invokevirtual #9 // java/lang/Integer.intValue:()I
40: iconst_1
41: iadd
42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
45: dup
46: astore_2
47: astore 4
49: aload_3
50: pop
51: goto 10
Autoboxing
Long total = 0;
for(Integer i = 0; i < N; i++) {
total += i;
}
00: lconst_0
01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
04: astore_1
05: iconst_0
06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
09: astore_2
10: aload_2
11: invokevirtual #9 // java/lang/Integer.intValue:()I
14: sipush N
17: if_icmpge 54
20: aload_1
21: invokevirtual #10 // java/lang/Long.longValue:()J
24: aload_2
25: invokevirtual #9 // java/lang/Integer.intValue:()I
28: i2l
29: ladd
30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
33: astore_1
34: aload_2
35: astore_3
36: aload_2
37: invokevirtual #9 // java/lang/Integer.intValue:()I
40: iconst_1
41: iadd
42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
45: dup
46: astore_2
47: astore 4
49: aload_3
50: pop
51: goto 10
Autoboxing
Long total = 0;
for(Integer i = 0; i < N; i++) {
total += i;
}
00: lconst_0
01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
04: astore_1
05: iconst_0
06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
09: astore_2
10: aload_2
11: invokevirtual #9 // java/lang/Integer.intValue:()I
14: sipush N
17: if_icmpge 54
20: aload_1
21: invokevirtual #10 // java/lang/Long.longValue:()J
24: aload_2
25: invokevirtual #9 // java/lang/Integer.intValue:()I
28: i2l
29: ladd
30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
33: astore_1
34: aload_2
35: astore_3
36: aload_2
37: invokevirtual #9 // java/lang/Integer.intValue:()I
40: iconst_1
41: iadd
42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
45: dup
46: astore_2
47: astore 4
49: aload_3
50: pop
51: goto 10
Autoboxing
Long total = 0;
for(Integer i = 0; i < N; i++) {
total += i;
}
00: lconst_0
01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
04: astore_1
05: iconst_0
06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
09: astore_2
10: aload_2
11: invokevirtual #9 // java/lang/Integer.intValue:()I
14: sipush N
17: if_icmpge 54
20: aload_1
21: invokevirtual #10 // java/lang/Long.longValue:()J
24: aload_2
25: invokevirtual #9 // java/lang/Integer.intValue:()I
28: i2l
29: ladd
30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
33: astore_1
34: aload_2
35: astore_3
36: aload_2
37: invokevirtual #9 // java/lang/Integer.intValue:()I
40: iconst_1
41: iadd
42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
45: dup
46: astore_2
47: astore 4
49: aload_3
50: pop
51: goto 10
Autoboxing
Long total = 0;
for(Integer i = 0; i < N; i++) {
total += i;
}
00: lconst_0
01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
04: astore_1
05: iconst_0
06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
09: astore_2
10: aload_2
11: invokevirtual #9 // java/lang/Integer.intValue:()I
14: sipush N
17: if_icmpge 54
20: aload_1
21: invokevirtual #10 // java/lang/Long.longValue:()J
24: aload_2
25: invokevirtual #9 // java/lang/Integer.intValue:()I
28: i2l
29: ladd
30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la
33: astore_1
34: aload_2
35: astore_3
36: aload_2
37: invokevirtual #9 // java/lang/Integer.intValue:()I
40: iconst_1
41: iadd
42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/
45: dup
46: astore_2
47: astore 4
49: aload_3
50: pop
51: goto 10
Autoboxing
Long total = 0;
for(Integer i = 0; i < N; i++) {
total += i;
}
// ?
00: lconst_0
01: invokestatic #7 // Method java/lang/Long.valueOf:(J)L
04: astore_1
05: iconst_0
06: invokestatic #8 // Method java/lang/Integer.valueOf:(I
09: astore_2
10: aload_2
11: invokevirtual #9 // Method java/lang/Integer.intValue:
14: sipush N
17: if_icmpge 54
20: aload_1
21: invokevirtual #10 // Method java/lang/Long.longValue:(
24: aload_2
25: invokevirtual #9 // Method java/lang/Integer.intValue:
28: i2l
29: ladd
30: invokestatic #7 // Method java/lang/Long.valueOf:(J)L
33: astore_1
34: aload_2
35: astore_3
36: aload_2
37: invokevirtual #9 // Method java/lang/Integer.intValue:
40: iconst_1
41: iadd
42: invokestatic #8 // Method java/lang/Integer.valueOf:(I
45: dup
46: astore_2
47: astore 4
49: aload_3
50: pop
51: goto 10
Autoboxing
This 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())
}
Autoboxing
Object 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())
}
Autoboxing
What about dex bytecode?
Autoboxing
D8 does not help in this situation
(neither Jack)
Autoboxing
What about the JIT compiler on
plain java?
Autoboxing
Let's run that loop
N times
(on my desktop computer)
N = 10.000.000.000
Autoboxing
Autoboxing
Let’s try it on Android
Dalvik VM & ART
Autoboxing
Language Additions
Use them wisely!
Sorting
No bytecode mumbo-jumbo
here
Let's sort some numbers…
Arrays.sort(...)
Difference between sorting
primitive types (int) &
objects (Integer)
Using int & Integer
When sorting objects java
uses a stable sort
Default java algorithm:
TimSort adaptation
Sorting primitives does not
require to be stable sort
Default java algorithm:
Dual-Pivot quicksort
Sorting
Use primitive types as much
as possible
Loops
What is going on behind the
scenes
Loops - List
ArrayList<Integer> list = new …
static long loopStandardList() {
long result = 0;
for(int i = 0; i < list.size(); i++) {
result += list.get(i);
}
return result;
}
ArrayList<Integer> list = new …
static long loopStandardList() {
long result = 0;
for(int i = 0; i < list.size(); i++) {
result += list.get(i);
}
return result;
}
07: lload_0
08: getstatic list
11: iload_2
12: invokevirtual java/util/ArrayList.get
15: checkcast java/lang/Integer
18: invokevirtual java/lang/Integer.intValue
21: i2l
22: ladd
23: lstore_0
24: iinc 2, 1
27: iload_2
28: getstatic list
31: invokevirtual java/util/ArrayList.size
34: if_icmplt 7
Loops - List
ArrayList<Integer> list = new …
static long loopStandardList() {
long result = 0;
for(int i = 0; i < list.size(); i++) {
result += list.get(i);
}
return result;
}
Loops - List 07: lload_0
08: getstatic list
11: iload_2
12: invokevirtual java/util/ArrayList.get
15: checkcast java/lang/Integer
18: invokevirtual java/lang/Integer.intValue
21: i2l
22: ladd
23: lstore_0
24: iinc 2, 1
27: iload_2
28: getstatic list
31: invokevirtual java/util/ArrayList.size
34: if_icmplt 7
ArrayList<Integer> list = new …
static long loopStandardList() {
long result = 0;
for(int i = 0; i < list.size(); i++) {
result += list.get(i);
}
return result;
}
Loops - List 07: lload_0
08: getstatic list
11: iload_2
12: invokevirtual java/util/ArrayList.get
15: checkcast java/lang/Integer
18: invokevirtual java/lang/Integer.intValue
21: i2l
22: ladd
23: lstore_0
24: iinc 2, 1
27: iload_2
28: getstatic list
31: invokevirtual java/util/ArrayList.size
34: if_icmplt 7
ArrayList<Integer> list = new …
static long loopStandardList() {
long result = 0;
for(int i = 0; i < list.size(); i++) {
result += list.get(i);
}
return result;
}
Loops - List 07: lload_0
08: getstatic list
11: iload_2
12: invokevirtual java/util/ArrayList.get
15: checkcast java/lang/Integer
18: invokevirtual java/lang/Integer.intValue
21: i2l
22: ladd
23: lstore_0
24: iinc 2, 1
27: iload_2
28: getstatic list
31: invokevirtual java/util/ArrayList.size
34: if_icmplt 7
Loops - foreach
ArrayList<Integer> list = new …
static long loopForeachList() {
long result = 0;
for(int v : list) {
result += v;
}
return result;
}
ArrayList<Integer> list = new …
static long loopForeachList() {
long result = 0;
for(int v : list) {
result += v;
}
return result;
}
12: aload_3
13: invokeinterface java/util/Iterator.next
18: checkcast java/lang/Integer
21: invokevirtual java/lang/Integer.intValue
24: istore_2
25: lload_0
26: iload_2
27: i2l
28: ladd
29: lstore_0
30: aload_3
31: invokeinterface java/util/Iterator.hasNext
36: ifne 12
Loops - foreach
ArrayList<Integer> list = new …
static long loopForeachList() {
long result = 0;
for(int v : list) {
result += v;
}
return result;
}
Loops - foreach
12: aload_3
13: invokeinterface java/util/Iterator.next
18: checkcast java/lang/Integer
21: invokevirtual java/lang/Integer.intValue
24: istore_2
25: lload_0
26: iload_2
27: i2l
28: ladd
29: lstore_0
30: aload_3
31: invokeinterface java/util/Iterator.hasNext
36: ifne 12
ArrayList<Integer> list = new …
static long loopForeachList() {
long result = 0;
for(int v : list) {
result += v;
}
return result;
}
Loops - foreach
12: aload_3
13: invokeinterface java/util/Iterator.next
18: checkcast java/lang/Integer
21: invokevirtual java/lang/Integer.intValue
24: istore_2
25: lload_0
26: iload_2
27: i2l
28: ladd
29: lstore_0
30: aload_3
31: invokeinterface java/util/Iterator.hasNext
36: ifne 12
Loops - Array
static int[] array = new ...
static long loopStandardArray() {
long result = 0;
for(int i = 0; i < array.length; i++) {
result += array[i];
}
return result;
}
static int[] array = new ...
static long loopStandardArray() {
long result = 0;
for(int i = 0; i < array.length; i++) {
result += array[i];
}
return result;
}
07: lload_0
08: getstatic array
11: iload_2
12: iaload
13: i2l
14: ladd
15: lstore_0
16: iinc 2, 1
19: iload_2
20: getstatic array
23: arraylength
24: if_icmplt 7
Loops - Array
static int[] array = new ...
static long loopStandardArray() {
long result = 0;
for(int i = 0; i < array.length; i++) {
result += array[i];
}
return result;
}
Loops - Array
07: lload_0
08: getstatic array
11: iload_2
12: iaload
13: i2l
14: ladd
15: lstore_0
16: iinc 2, 1
19: iload_2
20: getstatic array
23: arraylength
24: if_icmplt 7
static int[] array = new ...
static long loopStandardArray() {
long result = 0;
for(int i = 0; i < array.length; i++) {
result += array[i];
}
return result;
}
Loops - Array
07: lload_0
08: getstatic array
11: iload_2
12: iaload
13: i2l
14: ladd
15: lstore_0
16: iinc 2, 1
19: iload_2
20: getstatic array
23: arraylength
24: if_icmplt 7
Loops - size cached
static 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;
}
static 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 array
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
Loops - size cached
static 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;
}
Loops - size cached
12: lload_0
13: getstatic array
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
Loops - backwards
static int[] array = new ...
static long loopStandardArray () {
long result = 0;
for(int i = array.length - 1; i >= 0; i--) {
result += array[i];
}
return result;
}
static 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 array
16: iload_2
17: iaload
18: i2l
19: ladd
20: lstore_0
21: iinc 2, -1
24: iload_2
25: ifge 12
Loops - backwards
static int[] array = new ...
static long loopStandardArray () {
long result = 0;
for(int i = array.length - 1; i >= 0; i--) {
result += array[i];
}
return result;
}
Loops - backwards
12: lload_0
13: getstatic array
16: iload_2
17: iaload
18: i2l
19: ladd
20: lstore_0
21: iinc 2, -1
24: iload_2
25: ifge 12
The bytecode gobbledygook
The bytecode gobbledygook
Let’s check step by step…
Loops – foreach II
static long loopForeachArray(int[] array) {
long result = 0;
for(int v : array) {
result += v;
}
return result;
}
Loops – foreach II
static long loopForeachArray(int[] array) {
long result = 0;
for(int v : array) {
result += v;
}
return result;
}
00: lconst_0
01: lstore_1
02: aload_0
03: dup
04: astore 6
06: arraylength
07: istore 5
09: iconst_0
10: istore 4
12: goto 29
15: aload 6
17: iload 4
19: iaload
20: istore_3
21: lload_1
22: iload_3
23: i2l
24: ladd
25: lstore_1
26: iinc 4, 1
29: iload 4
31: iload 5
33: if_icmplt 15
0 array 4 -
1 - 5 -
2 - 6 -
3 - 7 -
Loops – foreach II
static long loopForeachArray(int[] array) {
long result = 0;
for(int v : array) {
result += v;
}
return result;
}
00: lconst_0
01: lstore_1
02: aload_0
03: dup
04: astore 6
06: arraylength
07: istore 5
09: iconst_0
10: istore 4
12: goto 29
15: aload 6
17: iload 4
19: iaload
20: istore_3
21: lload_1
22: iload_3
23: i2l
24: ladd
25: lstore_1
26: iinc 4, 1
29: iload 4
31: iload 5
33: if_icmplt 15
0 array 4 -
1 0 (result) 5 -
2 - 6 -
3 - 7 -
Loops – foreach II
static long loopForeachArray(int[] array) {
long result = 0;
for(int v : array) {
result += v;
}
return result;
}
00: lconst_0
01: lstore_1
02: aload_0
03: dup
04: astore 6
06: arraylength
07: istore 5
09: iconst_0
10: istore 4
12: goto 29
15: aload 6
17: iload 4
19: iaload
20: istore_3
21: lload_1
22: iload_3
23: i2l
24: ladd
25: lstore_1
26: iinc 4, 1
29: iload 4
31: iload 5
33: if_icmplt 15
0 array 4 -
1 0 (result) 5 -
2 - 6 array
3 - 7 -
Loops – foreach II
static long loopForeachArray(int[] array) {
long result = 0;
for(int v : array) {
result += v;
}
return result;
}
00: lconst_0
01: lstore_1
02: aload_0
03: dup
04: astore 6
06: arraylength
07: istore 5
09: iconst_0
10: istore 4
12: goto 29
15: aload 6
17: iload 4
19: iaload
20: istore_3
21: lload_1
22: iload_3
23: i2l
24: ladd
25: lstore_1
26: iinc 4, 1
29: iload 4
31: iload 5
33: if_icmplt 15
0 array 4 -
1 0 (result) 5 array.length
2 - 6 array
3 - 7 -
Loops – foreach II
static long loopForeachArray(int[] array) {
long result = 0;
for(int v : array) {
result += v;
}
return result;
}
00: lconst_0
01: lstore_1
02: aload_0
03: dup
04: astore 6
06: arraylength
07: istore 5
09: iconst_0
10: istore 4
12: goto 29
15: aload 6
17: iload 4
19: iaload
20: istore_3
21: lload_1
22: iload_3
23: i2l
24: ladd
25: lstore_1
26: iinc 4, 1
29: iload 4
31: iload 5
33: if_icmplt 15
0 array 4 0 (loop index)
1 0 (result) 5 array.length
2 - 6 array
3 - 7 -
Loops – foreach II
static long loopForeachArray(int[] array) {
long result = 0;
for(int v : array) {
result += v;
}
return result;
}
00: lconst_0
01: lstore_1
02: aload_0
03: dup
04: astore 6
06: arraylength
07: istore 5
09: iconst_0
10: istore 4
12: goto 29
15: aload 6
17: iload 4
19: iaload
20: istore_3
21: lload_1
22: iload_3
23: i2l
24: ladd
25: lstore_1
26: iinc 4, 1
29: iload 4
31: iload 5
33: if_icmplt 15
0 array 4 0 (loop index)
1 0 (result) 5 array.length
2 - 6 array
3 - 7 -
Loops – foreach II
static long loopForeachArray(int[] array) {
long result = 0;
for(int v : array) {
result += v;
}
return result;
}
00: lconst_0
01: lstore_1
02: aload_0
03: dup
04: astore 6
06: arraylength
07: istore 5
09: iconst_0
10: istore 4
12: goto 29
15: aload 6
17: iload 4
19: iaload
20: istore_3
21: lload_1
22: iload_3
23: i2l
24: ladd
25: lstore_1
26: iinc 4, 1
29: iload 4
31: iload 5
33: if_icmplt 15
0 array 4 0 (loop index)
1 0 (result) 5 array.length
2 - 6 array
3 array[index] 7 -
Loops – foreach II
static long loopForeachArray(int[] array) {
long result = 0;
for(int v : array) {
result += v;
}
return result;
}
00: lconst_0
01: lstore_1
02: aload_0
03: dup
04: astore 6
06: arraylength
07: istore 5
09: iconst_0
10: istore 4
12: goto 29
15: aload 6
17: iload 4
19: iaload
20: istore_3
21: lload_1
22: iload_3
23: i2l
24: ladd
25: lstore_1
26: iinc 4, 1
29: iload 4
31: iload 5
33: if_icmplt 15
0 array 4 0 (loop index)
1 0 + array[index] 5 array.length
2 - 6 array
3 array[index] 7 -
Loops – foreach II
static long loopForeachArray(int[] array) {
long result = 0;
for(int v : array) {
result += v;
}
return result;
}
00: lconst_0
01: lstore_1
02: aload_0
03: dup
04: astore 6
06: arraylength
07: istore 5
09: iconst_0
10: istore 4
12: goto 29
15: aload 6
17: iload 4
19: iaload
20: istore_3
21: lload_1
22: iload_3
23: i2l
24: ladd
25: lstore_1
26: iinc 4, 1
29: iload 4
31: iload 5
33: if_icmplt 15
0 array 4 0 (loop index) + 1
1 0 + array[index] 5 array.length
2 - 6 array
3 array[index] 7 -
→ 1,26% →
NOTASCALE
→ -18,33% →
Loops
Use arrays instead of lists
Manual bytecode
optimization
Worth it?
foreach loop 0: lconst_0
1: lstore_1
2: aload_0
3: dup
4: astore 6
6: arraylength
7: istore 5
9: iconst_0
10: istore 4
12: goto 29
15: aload 6
17: iload 4
19: iaload
20: istore_3
21: lload_1
22: iload_3
23: i2l
24: ladd
25: lstore_1
26: iinc 4, 1
29: iload 4
31: iload 5
33: 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_0
10: iload_1
11: iaload
12: i2l
13: ladd
14: iinc 1, 1
17: iload_1
18: iload_3
19: if_icmplt 9
Manual bytecode optimization
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_0
10: iload_1
11: iaload
12: i2l
13: ladd
14: iinc 1, 1
17: iload_1
18: iload_3
19: if_icmplt 9
Local variables
0 array 3 -
1 - 4 -
2 - 5 -
Stack
-
-
-
0: aload_0
1: arraylength
2: istore_3
3: iconst_0
4: istore_1
5: lconst_0
6: goto 17
9: aload_0
10: iload_1
11: iaload
12: i2l
13: ladd
14: iinc 1, 1
17: iload_1
18: iload_3
19: if_icmplt 9
Local variables
0 array 3 array.length
1 - 4 -
2 - 5 -
Stack
-
-
-
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_0
10: iload_1
11: iaload
12: i2l
13: ladd
14: iinc 1, 1
17: iload_1
18: iload_3
19: if_icmplt 9
Local variables
0 array 3 array.length
1 0 (index) 4 -
2 - 5 -
Stack
-
-
-
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_0
10: iload_1
11: iaload
12: i2l
13: ladd
14: iinc 1, 1
17: iload_1
18: iload_3
19: if_icmplt 9
Local variables
0 array 3 array.length
1 0 (index) 4 -
2 - 5 -
Stack
0 (result)
-
-
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_0
10: iload_1
11: iaload
12: i2l
13: ladd
14: iinc 1, 1
17: iload_1
18: iload_3
19: if_icmplt 9
Local variables
0 array 3 array.length
1 0 (index) 4 -
2 - 5 -
Stack
0 (result)
array[0]
-
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_0
10: iload_1
11: iaload
12: i2l
13: ladd
14: iinc 1, 1
17: iload_1
18: iload_3
19: if_icmplt 9
Local variables
0 array 3 array.length
1 0 (index) 4 -
2 - 5 -
Stack
0 + array[0]
-
-
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_0
10: iload_1
11: iaload
12: i2l
13: ladd
14: iinc 1, 1
17: iload_1
18: iload_3
19: if_icmplt 9
Local variables
0 array 3 array.length
1 0 (index) + 1 4 -
2 - 5 -
Stack
0 + array[0]
-
-
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_0
10: iload_1
11: iaload
12: i2l
13: ladd
14: iinc 1, 1
17: iload_1
18: iload_3
19: if_icmplt 9
Local variables
0 array 3 array.length
1 1 (index) 4 -
2 - 5 -
Stack
0 + array[0]
-
-
Manual bytecode optimization
The bytecode gobbledygook
Worth it?
Only in very specific cases. And
then you’re probably using the
wrong language.
Too much effort involved…
But let D8/R8/Proguard do it for you!
Calling a method
Is there an overhead?
Overhead of calling a method
for(int i = 0; i < N; i++) {
setVal(getVal() + 1);
}
for(int i = 0; i < N; i++) {
val = val + 1;
}
vs
The bytecode gobbledygook
String concatenation
The evil + sign
String concatenation
String str = "";
for(int i = 0; i < N; i++) {
str += OTHER_STR;
}
String concatenation
String str = "";
for(int i = 0; i < N; i++) {
str += OTHER_STR;
}
0: ldc String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: sipush N
9: if_icmpge 40
12: new class java/lang/StringBuilder
15: dup
16: invokespecial java/lang/StringBuilder."<init>"
19: aload_1
20: invokevirtual java/lang/StringBuilder.append
23: aload_0
24: getfield OTHER_STR
27: invokevirtual java/lang/StringBuilder.append
30: invokevirtual java/lang/StringBuilder.toString
33: astore_1
34: iinc 2, 1
37: goto 5
String concatenation
String str = "";
for(int i = 0; i < N; i++) {
str += OTHER_STR;
}
0: ldc String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: sipush N
9: if_icmpge 40
12: new class java/lang/StringBuilder
15: dup
16: invokespecial java/lang/StringBuilder."<init>"
19: aload_1
20: invokevirtual java/lang/StringBuilder.append
23: aload_0
24: getfield OTHER_STR
27: invokevirtual java/lang/StringBuilder.append
30: invokevirtual java/lang/StringBuilder.toString
33: astore_1
34: iinc 2, 1
37: goto 5
String concatenation
String str = "";
for(int i = 0; i < N; i++) {
str += OTHER_STR;
}
0: ldc String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: sipush N
9: if_icmpge 40
12: new class java/lang/StringBuilder
15: dup
16: invokespecial java/lang/StringBuilder."<init>"
19: aload_1
20: invokevirtual java/lang/StringBuilder.append
23: aload_0
24: getfield OTHER_STR
27: invokevirtual java/lang/StringBuilder.append
30: invokevirtual java/lang/StringBuilder.toString
33: astore_1
34: iinc 2, 1
37: goto 5
String concatenation
String str = "";
for(int i = 0; i < N; i++) {
str += OTHER_STR;
}
0: ldc String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: sipush N
9: if_icmpge 40
12: new class java/lang/StringBuilder
15: dup
16: invokespecial java/lang/StringBuilder."<init>"
19: aload_1
20: invokevirtual java/lang/StringBuilder.append
23: aload_0
24: getfield OTHER_STR
27: invokevirtual java/lang/StringBuilder.append
30: invokevirtual java/lang/StringBuilder.toString
33: astore_1
34: iinc 2, 1
37: goto 5
String concatenation
String str = "";
for(int i = 0; i < N; i++) {
str += OTHER_STR;
}
0: ldc String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: sipush N
9: if_icmpge 40
12: new class java/lang/StringBuilder
15: dup
16: invokespecial java/lang/StringBuilder."<init>"
19: aload_1
20: invokevirtual java/lang/StringBuilder.append
23: aload_0
24: getfield OTHER_STR
27: invokevirtual java/lang/StringBuilder.append
30: invokevirtual java/lang/StringBuilder.toString
33: astore_1
34: iinc 2, 1
37: goto 5
String concatenation
String str = "";
for(int i = 0; i < N; i++) {
str += OTHER_STR;
}
0: ldc String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: sipush N
9: if_icmpge 40
12: new class java/lang/StringBuilder
15: dup
16: invokespecial java/lang/StringBuilder."<init>"
19: aload_1
20: invokevirtual java/lang/StringBuilder.append
23: aload_0
24: getfield OTHER_STR
27: invokevirtual java/lang/StringBuilder.append
30: invokevirtual java/lang/StringBuilder.toString
33: astore_1
34: iinc 2, 1
37: goto 5
String str = "";
for(int i = 0; i < N; i++) {
StringBuilder sb = new StringBuilder();
sb.append(str);
sb.append(OTHER_STR);
str = sb.toString();
}
String concatenation
Object creation:
String str = "";
for(int i = 0; i < N; i++) {
StringBuilder sb = new StringBuilder();
sb.append(str);
sb.append(OTHER_STR);
str = sb.toString();
}
String concatenation
String concatenation
alternatives
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);
}
String.concat()
Object creation:
String str = "";
for(int i = 0; i < N; i++) {
str = str.concat(OTHER_STR);
}
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();
StringBuilder
sb = new StringBuilder()
for(int i = 0; i < N; i++) {
sb.append(OTHER_STR);
}
str = sb.toString();
0: ldc String
2: astore_1
3: new java/lang/StringBuilder
6: dup
7: invokespecial java/lang/StringBuilder."<init>"
10: astore_2
11: iconst_0
12: istore_3
13: iload_3
14: sipush N
17: if_icmpge 35
20: aload_2
21: aload_0
22: getfield OTHER_STR
25: invokevirtual java/lang/StringBuilder.append
28: pop
29: iinc 3, 1
32: goto 13
0: ldc String
2: astore_1
3: new java/lang/StringBuilder
6: dup
7: invokespecial java/lang/StringBuilder."<init>"
10: astore_2
11: iconst_0
12: istore_3
13: iload_3
14: sipush N
17: if_icmpge 35
20: aload_2
21: aload_0
22: getfield OTHER_STR
25: invokevirtual java/lang/StringBuilder.append
28: pop
29: iinc 3, 1
32: goto 13
sb = new StringBuilder()
for(int i = 0; i < N; i++) {
sb.append(OTHER_STR);
}
str = sb.toString();
StringBuilder
Object creation:
StringBuilder sb = new StringBuilder();
for(int i = 0; i < N; i++) {
sb.append(OTHER_STR);
}
str = sb.toString();
StringBuilder
String concatenation
Use StringBuilder (properly) as
much as possible. StringBuffer
is the thread safe
implementation.
Strings in case statements
public void taskStateMachine(String status) {
switch(status) {
case "PENDING":
System.out.println("Status pending");
break;
case "EXECUTING":
System.out.println("Status executing");
break;
}
}
The bytecode gobbledygook
The bytecode gobbledygook
Code optimization example:
yuv2rgb converter.
Always measure!
Source: Wikipedia
The bytecode gobbledygook
Slightly optimized version
precalc tables, fixed point
operations, 2 pixels per loop…
The bytecode gobbledygook
The bytecode gobbledygook
Lets compare:
Normal, minified, minified
with optimizations & jack
Minified = obfuscated using Proguard
Normal Minified Minified & optimized Jack
0
2000
4000
6000
8000
10000
12000
14000
16000
18000
20000
non-optimized
optimized
Tooling
Tooling
Java
• javap -c <classfile>
Android:
•Dexdump -d <dexfile>
Tooling
D8/R8
https://android.googlesource.com/platform/external/r8/
Krakatau
https://github.com/Storyyeller/Krakatau
Tooling – Disassembler - ART
adb pull /data/dalvik-
cache/arm/data@app@<package>-
1@base apk@classes.dex
adb shell oatdump --oat-file=/data/dalvik-
cache/arm/data@app@<package>-
1@base.apk@classes.dex
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 by @alblue
http://alblue.bandlem.com/2016/09/javaone-hotspot.html
Additional References
Sinking your teeth into bytecode by @jakewharton
http://jakewharton.com/sinking-your-teeth-into-bytecode/
Exploring Kotlin’s hidden costs by @BladeCoder
https://medium.com/@BladeCoder/exploring-kotlins-
hidden-costs-part-1-fbb9935d9b62
Performance measurements
Avoid doing multiple tests in one run
JIT might be evil!
Thank you!
http://blog.rafols.org
@rrafols
https://es.linkedin.com/in/raimonrafols

More Related Content

What's hot

Network lab manual
Network lab manualNetwork lab manual
Network lab manualPrabhu D
 
Network lap pgms 7th semester
Network lap pgms 7th semesterNetwork lap pgms 7th semester
Network lap pgms 7th semesterDOSONKA Group
 
What has to be paid attention when reviewing code of the library you develop
What has to be paid attention when reviewing code of the library you developWhat has to be paid attention when reviewing code of the library you develop
What has to be paid attention when reviewing code of the library you developAndrey Karpov
 
The LLDB Debugger in FreeBSD by Ed Maste
The LLDB Debugger in FreeBSD by Ed MasteThe LLDB Debugger in FreeBSD by Ed Maste
The LLDB Debugger in FreeBSD by Ed Masteeurobsdcon
 
Cisco IOS shellcode: All-in-one
Cisco IOS shellcode: All-in-oneCisco IOS shellcode: All-in-one
Cisco IOS shellcode: All-in-oneDefconRussia
 
Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++corehard_by
 
An Embedded Error Recovery and Debugging Mechanism for Scripting Language Ext...
An Embedded Error Recovery and Debugging Mechanism for Scripting Language Ext...An Embedded Error Recovery and Debugging Mechanism for Scripting Language Ext...
An Embedded Error Recovery and Debugging Mechanism for Scripting Language Ext...David Beazley (Dabeaz LLC)
 
Computer Networks Lab File
Computer Networks Lab FileComputer Networks Lab File
Computer Networks Lab FileKandarp Tiwari
 
2018 cosup-delete unused python code safely - english
2018 cosup-delete unused python code safely - english2018 cosup-delete unused python code safely - english
2018 cosup-delete unused python code safely - englishJen Yee Hong
 
Global Interpreter Lock: Episode I - Break the Seal
Global Interpreter Lock: Episode I - Break the SealGlobal Interpreter Lock: Episode I - Break the Seal
Global Interpreter Lock: Episode I - Break the SealTzung-Bi Shih
 
C Programming Training in Ambala ! Batra Computer Centre
C Programming Training in Ambala ! Batra Computer CentreC Programming Training in Ambala ! Batra Computer Centre
C Programming Training in Ambala ! Batra Computer Centrejatin batra
 
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java scriptCodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java scriptCodiLime
 
Kamil witecki asynchronous, yet readable, code
Kamil witecki asynchronous, yet readable, codeKamil witecki asynchronous, yet readable, code
Kamil witecki asynchronous, yet readable, codeKamil Witecki
 
A Replay Approach to Software Validation
A Replay Approach to Software ValidationA Replay Approach to Software Validation
A Replay Approach to Software ValidationJames Pascoe
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedPascal-Louis Perez
 
深入淺出C語言
深入淺出C語言深入淺出C語言
深入淺出C語言Simen Li
 
PVS-Studio, a solution for resource intensive applications development
PVS-Studio, a solution for resource intensive applications developmentPVS-Studio, a solution for resource intensive applications development
PVS-Studio, a solution for resource intensive applications developmentOOO "Program Verification Systems"
 

What's hot (20)

Network lab manual
Network lab manualNetwork lab manual
Network lab manual
 
Network lap pgms 7th semester
Network lap pgms 7th semesterNetwork lap pgms 7th semester
Network lap pgms 7th semester
 
What has to be paid attention when reviewing code of the library you develop
What has to be paid attention when reviewing code of the library you developWhat has to be paid attention when reviewing code of the library you develop
What has to be paid attention when reviewing code of the library you develop
 
IOS debugging
IOS debuggingIOS debugging
IOS debugging
 
The LLDB Debugger in FreeBSD by Ed Maste
The LLDB Debugger in FreeBSD by Ed MasteThe LLDB Debugger in FreeBSD by Ed Maste
The LLDB Debugger in FreeBSD by Ed Maste
 
Cisco IOS shellcode: All-in-one
Cisco IOS shellcode: All-in-oneCisco IOS shellcode: All-in-one
Cisco IOS shellcode: All-in-one
 
Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++
 
An Embedded Error Recovery and Debugging Mechanism for Scripting Language Ext...
An Embedded Error Recovery and Debugging Mechanism for Scripting Language Ext...An Embedded Error Recovery and Debugging Mechanism for Scripting Language Ext...
An Embedded Error Recovery and Debugging Mechanism for Scripting Language Ext...
 
Computer Networks Lab File
Computer Networks Lab FileComputer Networks Lab File
Computer Networks Lab File
 
2018 cosup-delete unused python code safely - english
2018 cosup-delete unused python code safely - english2018 cosup-delete unused python code safely - english
2018 cosup-delete unused python code safely - english
 
Zone IDA Proc
Zone IDA ProcZone IDA Proc
Zone IDA Proc
 
Global Interpreter Lock: Episode I - Break the Seal
Global Interpreter Lock: Episode I - Break the SealGlobal Interpreter Lock: Episode I - Break the Seal
Global Interpreter Lock: Episode I - Break the Seal
 
C Programming Training in Ambala ! Batra Computer Centre
C Programming Training in Ambala ! Batra Computer CentreC Programming Training in Ambala ! Batra Computer Centre
C Programming Training in Ambala ! Batra Computer Centre
 
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java scriptCodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
 
Kamil witecki asynchronous, yet readable, code
Kamil witecki asynchronous, yet readable, codeKamil witecki asynchronous, yet readable, code
Kamil witecki asynchronous, yet readable, code
 
A Replay Approach to Software Validation
A Replay Approach to Software ValidationA Replay Approach to Software Validation
A Replay Approach to Software Validation
 
.net progrmming part1
.net progrmming part1.net progrmming part1
.net progrmming part1
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
深入淺出C語言
深入淺出C語言深入淺出C語言
深入淺出C語言
 
PVS-Studio, a solution for resource intensive applications development
PVS-Studio, a solution for resource intensive applications developmentPVS-Studio, a solution for resource intensive applications development
PVS-Studio, a solution for resource intensive applications development
 

Similar to The bytecode gobbledygook

Improving Java performance at JBCNConf 2015
Improving Java performance at JBCNConf 2015Improving Java performance at JBCNConf 2015
Improving Java performance at JBCNConf 2015Raimon Ràfols
 
Improving Android Performance at Mobiconf 2014
Improving Android Performance at Mobiconf 2014Improving Android Performance at Mobiconf 2014
Improving Android Performance at Mobiconf 2014Raimon Ràfols
 
Introduction to Debuggers
Introduction to DebuggersIntroduction to Debuggers
Introduction to DebuggersSaumil Shah
 
HKG15-207: Advanced Toolchain Usage Part 3
HKG15-207: Advanced Toolchain Usage Part 3HKG15-207: Advanced Toolchain Usage Part 3
HKG15-207: Advanced Toolchain Usage Part 3Linaro
 
Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8Nikita Popov
 
Performance #5 cpu and battery
Performance #5  cpu and batteryPerformance #5  cpu and battery
Performance #5 cpu and batteryVitali Pekelis
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesGanesh Samarthyam
 
BlueHat Seattle 2019 || Modern Binary Analysis with ILs
BlueHat Seattle 2019 || Modern Binary Analysis with ILsBlueHat Seattle 2019 || Modern Binary Analysis with ILs
BlueHat Seattle 2019 || Modern Binary Analysis with ILsBlueHat Security Conference
 
Bytes in the Machine: Inside the CPython interpreter
Bytes in the Machine: Inside the CPython interpreterBytes in the Machine: Inside the CPython interpreter
Bytes in the Machine: Inside the CPython interpreterakaptur
 
Static analysis of C++ source code
Static analysis of C++ source codeStatic analysis of C++ source code
Static analysis of C++ source codeAndrey Karpov
 
Static analysis of C++ source code
Static analysis of C++ source codeStatic analysis of C++ source code
Static analysis of C++ source codePVS-Studio
 
Psimd open64 workshop_2012-new
Psimd open64 workshop_2012-newPsimd open64 workshop_2012-new
Psimd open64 workshop_2012-newdibyendu_das0708
 
Multiplatform JIT Code Generator for NetBSD by Alexander Nasonov
Multiplatform JIT Code Generator for NetBSD by Alexander NasonovMultiplatform JIT Code Generator for NetBSD by Alexander Nasonov
Multiplatform JIT Code Generator for NetBSD by Alexander Nasonoveurobsdcon
 
Java Bytecode Crash Course [Code One 2019]
Java Bytecode Crash Course [Code One 2019]Java Bytecode Crash Course [Code One 2019]
Java Bytecode Crash Course [Code One 2019]David Buck
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2goMoriyoshi Koizumi
 
Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015
Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015
Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015Windows Developer
 
2.1 ### uVision Project, (C) Keil Software .docx
2.1   ### uVision Project, (C) Keil Software    .docx2.1   ### uVision Project, (C) Keil Software    .docx
2.1 ### uVision Project, (C) Keil Software .docxtarifarmarie
 

Similar to The bytecode gobbledygook (20)

Improving Java performance at JBCNConf 2015
Improving Java performance at JBCNConf 2015Improving Java performance at JBCNConf 2015
Improving Java performance at JBCNConf 2015
 
Improving Android Performance at Mobiconf 2014
Improving Android Performance at Mobiconf 2014Improving Android Performance at Mobiconf 2014
Improving Android Performance at Mobiconf 2014
 
Boosting Developer Productivity with Clang
Boosting Developer Productivity with ClangBoosting Developer Productivity with Clang
Boosting Developer Productivity with Clang
 
Introduction to Debuggers
Introduction to DebuggersIntroduction to Debuggers
Introduction to Debuggers
 
HKG15-207: Advanced Toolchain Usage Part 3
HKG15-207: Advanced Toolchain Usage Part 3HKG15-207: Advanced Toolchain Usage Part 3
HKG15-207: Advanced Toolchain Usage Part 3
 
Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8
 
Staging driver sins
Staging driver sinsStaging driver sins
Staging driver sins
 
Performance #5 cpu and battery
Performance #5  cpu and batteryPerformance #5  cpu and battery
Performance #5 cpu and battery
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java Bytecodes
 
BlueHat Seattle 2019 || Modern Binary Analysis with ILs
BlueHat Seattle 2019 || Modern Binary Analysis with ILsBlueHat Seattle 2019 || Modern Binary Analysis with ILs
BlueHat Seattle 2019 || Modern Binary Analysis with ILs
 
Bytes in the Machine: Inside the CPython interpreter
Bytes in the Machine: Inside the CPython interpreterBytes in the Machine: Inside the CPython interpreter
Bytes in the Machine: Inside the CPython interpreter
 
Static analysis of C++ source code
Static analysis of C++ source codeStatic analysis of C++ source code
Static analysis of C++ source code
 
Static analysis of C++ source code
Static analysis of C++ source codeStatic analysis of C++ source code
Static analysis of C++ source code
 
Psimd open64 workshop_2012-new
Psimd open64 workshop_2012-newPsimd open64 workshop_2012-new
Psimd open64 workshop_2012-new
 
Multiplatform JIT Code Generator for NetBSD by Alexander Nasonov
Multiplatform JIT Code Generator for NetBSD by Alexander NasonovMultiplatform JIT Code Generator for NetBSD by Alexander Nasonov
Multiplatform JIT Code Generator for NetBSD by Alexander Nasonov
 
Java Bytecode Crash Course [Code One 2019]
Java Bytecode Crash Course [Code One 2019]Java Bytecode Crash Course [Code One 2019]
Java Bytecode Crash Course [Code One 2019]
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2go
 
Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015
Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015
Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015
 
Java Decompiler
Java DecompilerJava Decompiler
Java Decompiler
 
2.1 ### uVision Project, (C) Keil Software .docx
2.1   ### uVision Project, (C) Keil Software    .docx2.1   ### uVision Project, (C) Keil Software    .docx
2.1 ### uVision Project, (C) Keil Software .docx
 

More from Raimon Ràfols

Rendering Art on the Web - A Performance compendium
Rendering Art on the Web - A Performance compendiumRendering Art on the Web - A Performance compendium
Rendering Art on the Web - A Performance compendiumRaimon Ràfols
 
The Digital Evolution of Dinosaurs - MWCS 2017
The Digital Evolution of Dinosaurs - MWCS 2017The Digital Evolution of Dinosaurs - MWCS 2017
The Digital Evolution of Dinosaurs - MWCS 2017Raimon Ràfols
 
Iterate & Learn 2017 (català)
Iterate & Learn 2017 (català)Iterate & Learn 2017 (català)
Iterate & Learn 2017 (català)Raimon Ràfols
 
Iterate + learn - February 2016
Iterate + learn - February 2016Iterate + learn - February 2016
Iterate + learn - February 2016Raimon Ràfols
 
Playing with camera preview buffers on BlackBerry 10
Playing with camera preview buffers on BlackBerry 10Playing with camera preview buffers on BlackBerry 10
Playing with camera preview buffers on BlackBerry 10Raimon Ràfols
 

More from Raimon Ràfols (7)

Rendering Art on the Web - A Performance compendium
Rendering Art on the Web - A Performance compendiumRendering Art on the Web - A Performance compendium
Rendering Art on the Web - A Performance compendium
 
The Digital Evolution of Dinosaurs - MWCS 2017
The Digital Evolution of Dinosaurs - MWCS 2017The Digital Evolution of Dinosaurs - MWCS 2017
The Digital Evolution of Dinosaurs - MWCS 2017
 
Android Custom Views
Android Custom ViewsAndroid Custom Views
Android Custom Views
 
Iterate & Learn 2017
Iterate & Learn 2017Iterate & Learn 2017
Iterate & Learn 2017
 
Iterate & Learn 2017 (català)
Iterate & Learn 2017 (català)Iterate & Learn 2017 (català)
Iterate & Learn 2017 (català)
 
Iterate + learn - February 2016
Iterate + learn - February 2016Iterate + learn - February 2016
Iterate + learn - February 2016
 
Playing with camera preview buffers on BlackBerry 10
Playing with camera preview buffers on BlackBerry 10Playing with camera preview buffers on BlackBerry 10
Playing with camera preview buffers on BlackBerry 10
 

The bytecode gobbledygook

  • 2. Disclaimer: This presentation contains bytecode Content is my own experimentation and might differ on other environments
  • 3. Competitions Work 2015 Local winner 2016+ Ambassador 2016 Runner up 2018 Honorable mention Demoscene Speaker Author Entrepreneurship @rrafols
  • 4. Everything starts with our friend the java compiler.
  • 5. *.java → [javac] → *.class
  • 7. *.java → [javac] → *.class *.class → [dx] → dex file
  • 8. *.java → [javac] → *.class *.class → [dx] → dex dex → [dexopt] → opt. dex dex → [dex2oat] → native
  • 9. but change is coming! Jack & Jill
  • 10. but change is coming! Jack & Jill
  • 11. *.java → [jack] → dex file
  • 12. but change is still coming! D8 & R8
  • 13. *.java → [javac] → *.class *.class → [d8/r8] → dex file
  • 14. Let’s focus first on javac Javac vs other compilers
  • 17. javac Does not know on which architecture the code will be executed
  • 19. For this reason Java bytecode & operations are stack based
  • 20. Easy to interpret But not the most performant solution
  • 21. Quick example Stack based integer addition
  • 22. j = j + i
  • 26. add r01, r02, r01 or add eax, ebx
  • 27. Let’s make things interesting… j = j + i + k + w + h * 2 + p * p;
  • 29. 0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 5 10: iconst_2 11: imul 12: iadd 13: iload 6 15: iload 6 17: imul 18: iadd 19: istore_2 j = j + i + k + w + h * 2 + p * p; Local vars 1: i 2: j 3: k 4: w 5: h 6: p
  • 30. 0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 5 10: iconst_2 11: imul 12: iadd 13: iload 6 15: iload 6 17: imul 18: iadd 19: istore_2 j = j + i + k + w + h * 2 + p * p; Local vars 1: i 2: j 3: k 4: w 5: h 6: p
  • 31. 0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 5 10: iconst_2 11: imul 12: iadd 13: iload 6 15: iload 6 17: imul 18: iadd 19: istore_2 j = j + i + k + w + h * 2 + p * p; Local vars 1: i 2: j 3: k 4: w 5: h 6: p
  • 32. 0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 5 10: iconst_2 11: imul 12: iadd 13: iload 6 15: iload 6 17: imul 18: iadd 19: istore_2 j = j + i + k + w + h * 2 + p * p; Local vars 1: i 2: j 3: k 4: w 5: h 6: p
  • 33. 0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 5 10: iconst_2 11: imul 12: iadd 13: iload 6 15: iload 6 17: imul 18: iadd 19: istore_2 j = j + i + k + w + h * 2 + p * p; Local vars 1: i 2: j 3: k 4: w 5: h 6: p
  • 34. 0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 5 10: iconst_2 11: imul 12: iadd 13: iload 6 15: iload 6 17: imul 18: iadd 19: istore_2 j = j + i + k + w + h * 2 + p * p; Local vars 1: i 2: j 3: k 4: w 5: h 6: p
  • 35. 0: iload_2 1: iload_1 2: iadd 3: iload_3 4: iadd 5: iload 4 7: iadd 8: iload 5 10: iconst_2 11: imul 12: iadd 13: iload 6 15: iload 6 17: imul 18: iadd 19: istore_2 j = j + i + k + w + h * 2 + p * p; Local vars 1: i 2: j 3: k 4: w 5: h 6: p
  • 37. add r01, r02, r01 add r01, r03, r01 add r01, r04, r01 mul r07, r05, #2 add r01, r07, r01 mul r08, r06, r06 add r02, r08, r01 j = j + i + k + w + h * 2 + p * p; r01: i r02: j r03: k r04: w r05: h r06: p
  • 38. Java VM (JVM) Only the JVM knows the architecture where is running. In our previous example, we used up to 8 registers, but some CPUs might have less than 8 registers…
  • 39. Java VM (JVM) All optimizations are left to be done by the JVM
  • 40. Maybe takes this concept a bit too far...
  • 41. Imagine this simple C code #include <stdio.h> int main() { int a = 10; int b = 1 + 2 + 3 + 4 + 5 + 6 + a; printf("%dn", b); }
  • 42. GCC compiler #include <stdio.h> int main() { int a = 10; int b = 1 + 2 + 3 + 4 + 5 + 6 + a; printf("%dn", b); } … movl $31, %esi call _printf … * Using gcc & -O2 compiler option
  • 43. 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 ...
  • 44. Let's do a small change #include <stdio.h> int main() { int a = 10; int b = 1 + 2 + 3 + 4 + 5 + a + 6; printf("%dn", b); }
  • 45. GCC compiler #include <stdio.h> int main() { int a = 10; int b = 1 + 2 + 3 + 4 + 5 + a + 6; printf("%dn", b); } … movl $31, %esi call _printf … * Using gcc & -O2 compiler option
  • 46. 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 15 5: iload_1 6: iadd 7: bipush 6 9: iadd 10: istore_2
  • 47. 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); }
  • 48. javac 00: bipush 10 02: istore_1 03: iload_1 04: iconst_1 05: iadd 06: iconst_2 07: iadd 08: iconst_3 09: iadd 10: iconst_4 11: iadd 12: iconst_5 13: iadd 14: bipush 6 16: iadd 17: istore_2 public static void main(String args[]) { int a = 10; int b = a + 1 + 2 + 3 + 4 + 5 + 6; System.out.println(b); }
  • 49. On Android there was jack to the rescue...
  • 50. 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 31 2: sget-object v1, Ljava/lang/System; 4: invoke-virtual {v1, v0} 7: return-void ...
  • 51. but d8 does the job as well...
  • 52. d8 public static void main(String args[]) { int a = 10; int b = a + 1 + 2 + 3 + 4 + 5 + 6; System.out.println(b); } ... 0: sget-object v1, Ljava/lang/System;… 2: const/16 v0, #int 31 4: invoke-virtual {v1, v0} 7: return-void ...
  • 53. And on Java there is the JIT compiler to the rescue
  • 54. JIT assembly output public static void main(String args[]) { int a = 10; int b = a + 1 + 2 + 3 + 4 + 5 + 6; System.out.println(b); } ... 0x00000001104b2bff: mov eax, 0x0001f ... 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
  • 56. Autoboxing Transparent to the developer but compiler adds some 'extra' code
  • 57. Autoboxing long 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 21 10: lload_1 11: iload_3 12: i2l 13: ladd 14: lstore_1 15: iinc 3, 1 18: goto 4
  • 58. Autoboxing long 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 21 10: lload_1 11: iload_3 12: i2l 13: ladd 14: lstore_1 15: iinc 3, 1 18: goto 4
  • 59. Autoboxing long 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 21 10: lload_1 11: iload_3 12: i2l 13: ladd 14: lstore_1 15: iinc 3, 1 18: goto 4
  • 60. Autoboxing long 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 21 10: lload_1 11: iload_3 12: i2l 13: ladd 14: lstore_1 15: iinc 3, 1 18: goto 4 21:
  • 61. Autoboxing long 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 21 10: lload_1 11: iload_3 12: i2l 13: ladd 14: lstore_1 15: iinc 3, 1 18: goto 4
  • 62. Autoboxing long 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 21 10: lload_1 11: iload_3 12: i2l 13: ladd 14: lstore_1 15: iinc 3, 1 18: goto 4
  • 63. Autoboxing long 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 21 10: lload_1 11: iload_3 12: i2l 13: ladd 14: lstore_1 15: iinc 3, 1 18: goto 4
  • 64. Autoboxing Long total = 0; for(Integer i = 0; i < N; i++) { total += i; }
  • 65. Autoboxing Long total = 0; for(Integer i = 0; i < N; i++) { total += i; } 00: lconst_0 01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 04: astore_1 05: iconst_0 06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 09: astore_2 10: aload_2 11: invokevirtual #9 // java/lang/Integer.intValue:()I 14: sipush N 17: if_icmpge 54 20: aload_1 21: invokevirtual #10 // java/lang/Long.longValue:()J 24: aload_2 25: invokevirtual #9 // java/lang/Integer.intValue:()I 28: i2l 29: ladd 30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // java/lang/Integer.intValue:()I 40: iconst_1 41: iadd 42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 45: dup 46: astore_2 47: astore 4 49: aload_3 50: pop 51: goto 10
  • 66. Autoboxing Long total = 0; for(Integer i = 0; i < N; i++) { total += i; } 00: lconst_0 01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 04: astore_1 05: iconst_0 06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 09: astore_2 10: aload_2 11: invokevirtual #9 // java/lang/Integer.intValue:()I 14: sipush N 17: if_icmpge 54 20: aload_1 21: invokevirtual #10 // java/lang/Long.longValue:()J 24: aload_2 25: invokevirtual #9 // java/lang/Integer.intValue:()I 28: i2l 29: ladd 30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // java/lang/Integer.intValue:()I 40: iconst_1 41: iadd 42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 45: dup 46: astore_2 47: astore 4 49: aload_3 50: pop 51: goto 10
  • 67. Autoboxing Long total = 0; for(Integer i = 0; i < N; i++) { total += i; } 00: lconst_0 01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 04: astore_1 05: iconst_0 06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 09: astore_2 10: aload_2 11: invokevirtual #9 // java/lang/Integer.intValue:()I 14: sipush N 17: if_icmpge 54 20: aload_1 21: invokevirtual #10 // java/lang/Long.longValue:()J 24: aload_2 25: invokevirtual #9 // java/lang/Integer.intValue:()I 28: i2l 29: ladd 30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // java/lang/Integer.intValue:()I 40: iconst_1 41: iadd 42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 45: dup 46: astore_2 47: astore 4 49: aload_3 50: pop 51: goto 10
  • 68. Autoboxing Long total = 0; for(Integer i = 0; i < N; i++) { total += i; } 00: lconst_0 01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 04: astore_1 05: iconst_0 06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 09: astore_2 10: aload_2 11: invokevirtual #9 // java/lang/Integer.intValue:()I 14: sipush N 17: if_icmpge 54 20: aload_1 21: invokevirtual #10 // java/lang/Long.longValue:()J 24: aload_2 25: invokevirtual #9 // java/lang/Integer.intValue:()I 28: i2l 29: ladd 30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // java/lang/Integer.intValue:()I 40: iconst_1 41: iadd 42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 45: dup 46: astore_2 47: astore 4 49: aload_3 50: pop 51: goto 10
  • 69. Autoboxing Long total = 0; for(Integer i = 0; i < N; i++) { total += i; } 00: lconst_0 01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 04: astore_1 05: iconst_0 06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 09: astore_2 10: aload_2 11: invokevirtual #9 // java/lang/Integer.intValue:()I 14: sipush N 17: if_icmpge 54 20: aload_1 21: invokevirtual #10 // java/lang/Long.longValue:()J 24: aload_2 25: invokevirtual #9 // java/lang/Integer.intValue:()I 28: i2l 29: ladd 30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // java/lang/Integer.intValue:()I 40: iconst_1 41: iadd 42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 45: dup 46: astore_2 47: astore 4 49: aload_3 50: pop 51: goto 10
  • 70. Autoboxing Long total = 0; for(Integer i = 0; i < N; i++) { total += i; } 00: lconst_0 01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 04: astore_1 05: iconst_0 06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 09: astore_2 10: aload_2 11: invokevirtual #9 // java/lang/Integer.intValue:()I 14: sipush N 17: if_icmpge 54 20: aload_1 21: invokevirtual #10 // java/lang/Long.longValue:()J 24: aload_2 25: invokevirtual #9 // java/lang/Integer.intValue:()I 28: i2l 29: ladd 30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // java/lang/Integer.intValue:()I 40: iconst_1 41: iadd 42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 45: dup 46: astore_2 47: astore 4 49: aload_3 50: pop 51: goto 10
  • 71. Autoboxing Long total = 0; for(Integer i = 0; i < N; i++) { total += i; } 00: lconst_0 01: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 04: astore_1 05: iconst_0 06: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 09: astore_2 10: aload_2 11: invokevirtual #9 // java/lang/Integer.intValue:()I 14: sipush N 17: if_icmpge 54 20: aload_1 21: invokevirtual #10 // java/lang/Long.longValue:()J 24: aload_2 25: invokevirtual #9 // java/lang/Integer.intValue:()I 28: i2l 29: ladd 30: invokestatic #7 // java/lang/Long.valueOf:(J)Ljava/la 33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // java/lang/Integer.intValue:()I 40: iconst_1 41: iadd 42: invokestatic #8 // java/lang/Integer.valueOf:(I)Ljava/ 45: dup 46: astore_2 47: astore 4 49: aload_3 50: pop 51: goto 10
  • 72. Autoboxing Long total = 0; for(Integer i = 0; i < N; i++) { total += i; } // ? 00: lconst_0 01: invokestatic #7 // Method java/lang/Long.valueOf:(J)L 04: astore_1 05: iconst_0 06: invokestatic #8 // Method java/lang/Integer.valueOf:(I 09: astore_2 10: aload_2 11: invokevirtual #9 // Method java/lang/Integer.intValue: 14: sipush N 17: if_icmpge 54 20: aload_1 21: invokevirtual #10 // Method java/lang/Long.longValue:( 24: aload_2 25: invokevirtual #9 // Method java/lang/Integer.intValue: 28: i2l 29: ladd 30: invokestatic #7 // Method java/lang/Long.valueOf:(J)L 33: astore_1 34: aload_2 35: astore_3 36: aload_2 37: invokevirtual #9 // Method java/lang/Integer.intValue: 40: iconst_1 41: iadd 42: invokestatic #8 // Method java/lang/Integer.valueOf:(I 45: dup 46: astore_2 47: astore 4 49: aload_3 50: pop 51: goto 10
  • 73. Autoboxing This 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()) }
  • 74. Autoboxing Object 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()) }
  • 76. Autoboxing D8 does not help in this situation (neither Jack)
  • 77. Autoboxing What about the JIT compiler on plain java?
  • 78. Autoboxing Let's run that loop N times (on my desktop computer) N = 10.000.000.000
  • 80. Autoboxing Let’s try it on Android Dalvik VM & ART
  • 84. Let's sort some numbers… Arrays.sort(...)
  • 85. Difference between sorting primitive types (int) & objects (Integer)
  • 86. Using int & Integer
  • 87. When sorting objects java uses a stable sort Default java algorithm: TimSort adaptation
  • 88. Sorting primitives does not require to be stable sort Default java algorithm: Dual-Pivot quicksort
  • 89. Sorting Use primitive types as much as possible
  • 90. Loops What is going on behind the scenes
  • 91. Loops - List ArrayList<Integer> list = new … static long loopStandardList() { long result = 0; for(int i = 0; i < list.size(); i++) { result += list.get(i); } return result; }
  • 92. ArrayList<Integer> list = new … static long loopStandardList() { long result = 0; for(int i = 0; i < list.size(); i++) { result += list.get(i); } return result; } 07: lload_0 08: getstatic list 11: iload_2 12: invokevirtual java/util/ArrayList.get 15: checkcast java/lang/Integer 18: invokevirtual java/lang/Integer.intValue 21: i2l 22: ladd 23: lstore_0 24: iinc 2, 1 27: iload_2 28: getstatic list 31: invokevirtual java/util/ArrayList.size 34: if_icmplt 7 Loops - List
  • 93. ArrayList<Integer> list = new … static long loopStandardList() { long result = 0; for(int i = 0; i < list.size(); i++) { result += list.get(i); } return result; } Loops - List 07: lload_0 08: getstatic list 11: iload_2 12: invokevirtual java/util/ArrayList.get 15: checkcast java/lang/Integer 18: invokevirtual java/lang/Integer.intValue 21: i2l 22: ladd 23: lstore_0 24: iinc 2, 1 27: iload_2 28: getstatic list 31: invokevirtual java/util/ArrayList.size 34: if_icmplt 7
  • 94. ArrayList<Integer> list = new … static long loopStandardList() { long result = 0; for(int i = 0; i < list.size(); i++) { result += list.get(i); } return result; } Loops - List 07: lload_0 08: getstatic list 11: iload_2 12: invokevirtual java/util/ArrayList.get 15: checkcast java/lang/Integer 18: invokevirtual java/lang/Integer.intValue 21: i2l 22: ladd 23: lstore_0 24: iinc 2, 1 27: iload_2 28: getstatic list 31: invokevirtual java/util/ArrayList.size 34: if_icmplt 7
  • 95. ArrayList<Integer> list = new … static long loopStandardList() { long result = 0; for(int i = 0; i < list.size(); i++) { result += list.get(i); } return result; } Loops - List 07: lload_0 08: getstatic list 11: iload_2 12: invokevirtual java/util/ArrayList.get 15: checkcast java/lang/Integer 18: invokevirtual java/lang/Integer.intValue 21: i2l 22: ladd 23: lstore_0 24: iinc 2, 1 27: iload_2 28: getstatic list 31: invokevirtual java/util/ArrayList.size 34: if_icmplt 7
  • 96. Loops - foreach ArrayList<Integer> list = new … static long loopForeachList() { long result = 0; for(int v : list) { result += v; } return result; }
  • 97. ArrayList<Integer> list = new … static long loopForeachList() { long result = 0; for(int v : list) { result += v; } return result; } 12: aload_3 13: invokeinterface java/util/Iterator.next 18: checkcast java/lang/Integer 21: invokevirtual java/lang/Integer.intValue 24: istore_2 25: lload_0 26: iload_2 27: i2l 28: ladd 29: lstore_0 30: aload_3 31: invokeinterface java/util/Iterator.hasNext 36: ifne 12 Loops - foreach
  • 98. ArrayList<Integer> list = new … static long loopForeachList() { long result = 0; for(int v : list) { result += v; } return result; } Loops - foreach 12: aload_3 13: invokeinterface java/util/Iterator.next 18: checkcast java/lang/Integer 21: invokevirtual java/lang/Integer.intValue 24: istore_2 25: lload_0 26: iload_2 27: i2l 28: ladd 29: lstore_0 30: aload_3 31: invokeinterface java/util/Iterator.hasNext 36: ifne 12
  • 99. ArrayList<Integer> list = new … static long loopForeachList() { long result = 0; for(int v : list) { result += v; } return result; } Loops - foreach 12: aload_3 13: invokeinterface java/util/Iterator.next 18: checkcast java/lang/Integer 21: invokevirtual java/lang/Integer.intValue 24: istore_2 25: lload_0 26: iload_2 27: i2l 28: ladd 29: lstore_0 30: aload_3 31: invokeinterface java/util/Iterator.hasNext 36: ifne 12
  • 100. Loops - Array static int[] array = new ... static long loopStandardArray() { long result = 0; for(int i = 0; i < array.length; i++) { result += array[i]; } return result; }
  • 101. static int[] array = new ... static long loopStandardArray() { long result = 0; for(int i = 0; i < array.length; i++) { result += array[i]; } return result; } 07: lload_0 08: getstatic array 11: iload_2 12: iaload 13: i2l 14: ladd 15: lstore_0 16: iinc 2, 1 19: iload_2 20: getstatic array 23: arraylength 24: if_icmplt 7 Loops - Array
  • 102. static int[] array = new ... static long loopStandardArray() { long result = 0; for(int i = 0; i < array.length; i++) { result += array[i]; } return result; } Loops - Array 07: lload_0 08: getstatic array 11: iload_2 12: iaload 13: i2l 14: ladd 15: lstore_0 16: iinc 2, 1 19: iload_2 20: getstatic array 23: arraylength 24: if_icmplt 7
  • 103. static int[] array = new ... static long loopStandardArray() { long result = 0; for(int i = 0; i < array.length; i++) { result += array[i]; } return result; } Loops - Array 07: lload_0 08: getstatic array 11: iload_2 12: iaload 13: i2l 14: ladd 15: lstore_0 16: iinc 2, 1 19: iload_2 20: getstatic array 23: arraylength 24: if_icmplt 7
  • 104. Loops - size cached static 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; }
  • 105. static 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 array 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 Loops - size cached
  • 106. static 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; } Loops - size cached 12: lload_0 13: getstatic array 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
  • 107. Loops - backwards static int[] array = new ... static long loopStandardArray () { long result = 0; for(int i = array.length - 1; i >= 0; i--) { result += array[i]; } return result; }
  • 108. static 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 array 16: iload_2 17: iaload 18: i2l 19: ladd 20: lstore_0 21: iinc 2, -1 24: iload_2 25: ifge 12 Loops - backwards
  • 109. static int[] array = new ... static long loopStandardArray () { long result = 0; for(int i = array.length - 1; i >= 0; i--) { result += array[i]; } return result; } Loops - backwards 12: lload_0 13: getstatic array 16: iload_2 17: iaload 18: i2l 19: ladd 20: lstore_0 21: iinc 2, -1 24: iload_2 25: ifge 12
  • 112. Let’s check step by step…
  • 113. Loops – foreach II static long loopForeachArray(int[] array) { long result = 0; for(int v : array) { result += v; } return result; }
  • 114. Loops – foreach II static long loopForeachArray(int[] array) { long result = 0; for(int v : array) { result += v; } return result; } 00: lconst_0 01: lstore_1 02: aload_0 03: dup 04: astore 6 06: arraylength 07: istore 5 09: iconst_0 10: istore 4 12: goto 29 15: aload 6 17: iload 4 19: iaload 20: istore_3 21: lload_1 22: iload_3 23: i2l 24: ladd 25: lstore_1 26: iinc 4, 1 29: iload 4 31: iload 5 33: if_icmplt 15 0 array 4 - 1 - 5 - 2 - 6 - 3 - 7 -
  • 115. Loops – foreach II static long loopForeachArray(int[] array) { long result = 0; for(int v : array) { result += v; } return result; } 00: lconst_0 01: lstore_1 02: aload_0 03: dup 04: astore 6 06: arraylength 07: istore 5 09: iconst_0 10: istore 4 12: goto 29 15: aload 6 17: iload 4 19: iaload 20: istore_3 21: lload_1 22: iload_3 23: i2l 24: ladd 25: lstore_1 26: iinc 4, 1 29: iload 4 31: iload 5 33: if_icmplt 15 0 array 4 - 1 0 (result) 5 - 2 - 6 - 3 - 7 -
  • 116. Loops – foreach II static long loopForeachArray(int[] array) { long result = 0; for(int v : array) { result += v; } return result; } 00: lconst_0 01: lstore_1 02: aload_0 03: dup 04: astore 6 06: arraylength 07: istore 5 09: iconst_0 10: istore 4 12: goto 29 15: aload 6 17: iload 4 19: iaload 20: istore_3 21: lload_1 22: iload_3 23: i2l 24: ladd 25: lstore_1 26: iinc 4, 1 29: iload 4 31: iload 5 33: if_icmplt 15 0 array 4 - 1 0 (result) 5 - 2 - 6 array 3 - 7 -
  • 117. Loops – foreach II static long loopForeachArray(int[] array) { long result = 0; for(int v : array) { result += v; } return result; } 00: lconst_0 01: lstore_1 02: aload_0 03: dup 04: astore 6 06: arraylength 07: istore 5 09: iconst_0 10: istore 4 12: goto 29 15: aload 6 17: iload 4 19: iaload 20: istore_3 21: lload_1 22: iload_3 23: i2l 24: ladd 25: lstore_1 26: iinc 4, 1 29: iload 4 31: iload 5 33: if_icmplt 15 0 array 4 - 1 0 (result) 5 array.length 2 - 6 array 3 - 7 -
  • 118. Loops – foreach II static long loopForeachArray(int[] array) { long result = 0; for(int v : array) { result += v; } return result; } 00: lconst_0 01: lstore_1 02: aload_0 03: dup 04: astore 6 06: arraylength 07: istore 5 09: iconst_0 10: istore 4 12: goto 29 15: aload 6 17: iload 4 19: iaload 20: istore_3 21: lload_1 22: iload_3 23: i2l 24: ladd 25: lstore_1 26: iinc 4, 1 29: iload 4 31: iload 5 33: if_icmplt 15 0 array 4 0 (loop index) 1 0 (result) 5 array.length 2 - 6 array 3 - 7 -
  • 119. Loops – foreach II static long loopForeachArray(int[] array) { long result = 0; for(int v : array) { result += v; } return result; } 00: lconst_0 01: lstore_1 02: aload_0 03: dup 04: astore 6 06: arraylength 07: istore 5 09: iconst_0 10: istore 4 12: goto 29 15: aload 6 17: iload 4 19: iaload 20: istore_3 21: lload_1 22: iload_3 23: i2l 24: ladd 25: lstore_1 26: iinc 4, 1 29: iload 4 31: iload 5 33: if_icmplt 15 0 array 4 0 (loop index) 1 0 (result) 5 array.length 2 - 6 array 3 - 7 -
  • 120. Loops – foreach II static long loopForeachArray(int[] array) { long result = 0; for(int v : array) { result += v; } return result; } 00: lconst_0 01: lstore_1 02: aload_0 03: dup 04: astore 6 06: arraylength 07: istore 5 09: iconst_0 10: istore 4 12: goto 29 15: aload 6 17: iload 4 19: iaload 20: istore_3 21: lload_1 22: iload_3 23: i2l 24: ladd 25: lstore_1 26: iinc 4, 1 29: iload 4 31: iload 5 33: if_icmplt 15 0 array 4 0 (loop index) 1 0 (result) 5 array.length 2 - 6 array 3 array[index] 7 -
  • 121. Loops – foreach II static long loopForeachArray(int[] array) { long result = 0; for(int v : array) { result += v; } return result; } 00: lconst_0 01: lstore_1 02: aload_0 03: dup 04: astore 6 06: arraylength 07: istore 5 09: iconst_0 10: istore 4 12: goto 29 15: aload 6 17: iload 4 19: iaload 20: istore_3 21: lload_1 22: iload_3 23: i2l 24: ladd 25: lstore_1 26: iinc 4, 1 29: iload 4 31: iload 5 33: if_icmplt 15 0 array 4 0 (loop index) 1 0 + array[index] 5 array.length 2 - 6 array 3 array[index] 7 -
  • 122. Loops – foreach II static long loopForeachArray(int[] array) { long result = 0; for(int v : array) { result += v; } return result; } 00: lconst_0 01: lstore_1 02: aload_0 03: dup 04: astore 6 06: arraylength 07: istore 5 09: iconst_0 10: istore 4 12: goto 29 15: aload 6 17: iload 4 19: iaload 20: istore_3 21: lload_1 22: iload_3 23: i2l 24: ladd 25: lstore_1 26: iinc 4, 1 29: iload 4 31: iload 5 33: if_icmplt 15 0 array 4 0 (loop index) + 1 1 0 + array[index] 5 array.length 2 - 6 array 3 array[index] 7 -
  • 127. foreach loop 0: lconst_0 1: lstore_1 2: aload_0 3: dup 4: astore 6 6: arraylength 7: istore 5 9: iconst_0 10: istore 4 12: goto 29 15: aload 6 17: iload 4 19: iaload 20: istore_3 21: lload_1 22: iload_3 23: i2l 24: ladd 25: lstore_1 26: iinc 4, 1 29: iload 4 31: iload 5 33: 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_0 10: iload_1 11: iaload 12: i2l 13: ladd 14: iinc 1, 1 17: iload_1 18: iload_3 19: if_icmplt 9 Manual bytecode optimization
  • 128. 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_0 10: iload_1 11: iaload 12: i2l 13: ladd 14: iinc 1, 1 17: iload_1 18: iload_3 19: if_icmplt 9 Local variables 0 array 3 - 1 - 4 - 2 - 5 - Stack - - -
  • 129. 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_0 10: iload_1 11: iaload 12: i2l 13: ladd 14: iinc 1, 1 17: iload_1 18: iload_3 19: if_icmplt 9 Local variables 0 array 3 array.length 1 - 4 - 2 - 5 - Stack - - - Manual bytecode optimization
  • 130. 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_0 10: iload_1 11: iaload 12: i2l 13: ladd 14: iinc 1, 1 17: iload_1 18: iload_3 19: if_icmplt 9 Local variables 0 array 3 array.length 1 0 (index) 4 - 2 - 5 - Stack - - - Manual bytecode optimization
  • 131. 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_0 10: iload_1 11: iaload 12: i2l 13: ladd 14: iinc 1, 1 17: iload_1 18: iload_3 19: if_icmplt 9 Local variables 0 array 3 array.length 1 0 (index) 4 - 2 - 5 - Stack 0 (result) - - Manual bytecode optimization
  • 132. 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_0 10: iload_1 11: iaload 12: i2l 13: ladd 14: iinc 1, 1 17: iload_1 18: iload_3 19: if_icmplt 9 Local variables 0 array 3 array.length 1 0 (index) 4 - 2 - 5 - Stack 0 (result) array[0] - Manual bytecode optimization
  • 133. 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_0 10: iload_1 11: iaload 12: i2l 13: ladd 14: iinc 1, 1 17: iload_1 18: iload_3 19: if_icmplt 9 Local variables 0 array 3 array.length 1 0 (index) 4 - 2 - 5 - Stack 0 + array[0] - - Manual bytecode optimization
  • 134. 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_0 10: iload_1 11: iaload 12: i2l 13: ladd 14: iinc 1, 1 17: iload_1 18: iload_3 19: if_icmplt 9 Local variables 0 array 3 array.length 1 0 (index) + 1 4 - 2 - 5 - Stack 0 + array[0] - - Manual bytecode optimization
  • 135. 0: aload_0 1: arraylength 2: istore_3 3: iconst_0 4: istore_1 5: lconst_0 6: goto 17 9: aload_0 10: iload_1 11: iaload 12: i2l 13: ladd 14: iinc 1, 1 17: iload_1 18: iload_3 19: if_icmplt 9 Local variables 0 array 3 array.length 1 1 (index) 4 - 2 - 5 - Stack 0 + array[0] - - Manual bytecode optimization
  • 137. Worth it? Only in very specific cases. And then you’re probably using the wrong language. Too much effort involved… But let D8/R8/Proguard do it for you!
  • 138. Calling a method Is there an overhead?
  • 139. Overhead of calling a method for(int i = 0; i < N; i++) { setVal(getVal() + 1); } for(int i = 0; i < N; i++) { val = val + 1; } vs
  • 142. String concatenation String str = ""; for(int i = 0; i < N; i++) { str += OTHER_STR; }
  • 143. String concatenation String str = ""; for(int i = 0; i < N; i++) { str += OTHER_STR; } 0: ldc String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: sipush N 9: if_icmpge 40 12: new class java/lang/StringBuilder 15: dup 16: invokespecial java/lang/StringBuilder."<init>" 19: aload_1 20: invokevirtual java/lang/StringBuilder.append 23: aload_0 24: getfield OTHER_STR 27: invokevirtual java/lang/StringBuilder.append 30: invokevirtual java/lang/StringBuilder.toString 33: astore_1 34: iinc 2, 1 37: goto 5
  • 144. String concatenation String str = ""; for(int i = 0; i < N; i++) { str += OTHER_STR; } 0: ldc String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: sipush N 9: if_icmpge 40 12: new class java/lang/StringBuilder 15: dup 16: invokespecial java/lang/StringBuilder."<init>" 19: aload_1 20: invokevirtual java/lang/StringBuilder.append 23: aload_0 24: getfield OTHER_STR 27: invokevirtual java/lang/StringBuilder.append 30: invokevirtual java/lang/StringBuilder.toString 33: astore_1 34: iinc 2, 1 37: goto 5
  • 145. String concatenation String str = ""; for(int i = 0; i < N; i++) { str += OTHER_STR; } 0: ldc String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: sipush N 9: if_icmpge 40 12: new class java/lang/StringBuilder 15: dup 16: invokespecial java/lang/StringBuilder."<init>" 19: aload_1 20: invokevirtual java/lang/StringBuilder.append 23: aload_0 24: getfield OTHER_STR 27: invokevirtual java/lang/StringBuilder.append 30: invokevirtual java/lang/StringBuilder.toString 33: astore_1 34: iinc 2, 1 37: goto 5
  • 146. String concatenation String str = ""; for(int i = 0; i < N; i++) { str += OTHER_STR; } 0: ldc String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: sipush N 9: if_icmpge 40 12: new class java/lang/StringBuilder 15: dup 16: invokespecial java/lang/StringBuilder."<init>" 19: aload_1 20: invokevirtual java/lang/StringBuilder.append 23: aload_0 24: getfield OTHER_STR 27: invokevirtual java/lang/StringBuilder.append 30: invokevirtual java/lang/StringBuilder.toString 33: astore_1 34: iinc 2, 1 37: goto 5
  • 147. String concatenation String str = ""; for(int i = 0; i < N; i++) { str += OTHER_STR; } 0: ldc String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: sipush N 9: if_icmpge 40 12: new class java/lang/StringBuilder 15: dup 16: invokespecial java/lang/StringBuilder."<init>" 19: aload_1 20: invokevirtual java/lang/StringBuilder.append 23: aload_0 24: getfield OTHER_STR 27: invokevirtual java/lang/StringBuilder.append 30: invokevirtual java/lang/StringBuilder.toString 33: astore_1 34: iinc 2, 1 37: goto 5
  • 148. String concatenation String str = ""; for(int i = 0; i < N; i++) { str += OTHER_STR; } 0: ldc String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: sipush N 9: if_icmpge 40 12: new class java/lang/StringBuilder 15: dup 16: invokespecial java/lang/StringBuilder."<init>" 19: aload_1 20: invokevirtual java/lang/StringBuilder.append 23: aload_0 24: getfield OTHER_STR 27: invokevirtual java/lang/StringBuilder.append 30: invokevirtual java/lang/StringBuilder.toString 33: astore_1 34: iinc 2, 1 37: goto 5
  • 149. String str = ""; for(int i = 0; i < N; i++) { StringBuilder sb = new StringBuilder(); sb.append(str); sb.append(OTHER_STR); str = sb.toString(); } String concatenation
  • 150. Object creation: String str = ""; for(int i = 0; i < N; i++) { StringBuilder sb = new StringBuilder(); sb.append(str); sb.append(OTHER_STR); str = sb.toString(); } String concatenation
  • 152. 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); }
  • 153. String.concat() Object creation: String str = ""; for(int i = 0; i < N; i++) { str = str.concat(OTHER_STR); }
  • 154. 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();
  • 155. StringBuilder sb = new StringBuilder() for(int i = 0; i < N; i++) { sb.append(OTHER_STR); } str = sb.toString(); 0: ldc String 2: astore_1 3: new java/lang/StringBuilder 6: dup 7: invokespecial java/lang/StringBuilder."<init>" 10: astore_2 11: iconst_0 12: istore_3 13: iload_3 14: sipush N 17: if_icmpge 35 20: aload_2 21: aload_0 22: getfield OTHER_STR 25: invokevirtual java/lang/StringBuilder.append 28: pop 29: iinc 3, 1 32: goto 13
  • 156. 0: ldc String 2: astore_1 3: new java/lang/StringBuilder 6: dup 7: invokespecial java/lang/StringBuilder."<init>" 10: astore_2 11: iconst_0 12: istore_3 13: iload_3 14: sipush N 17: if_icmpge 35 20: aload_2 21: aload_0 22: getfield OTHER_STR 25: invokevirtual java/lang/StringBuilder.append 28: pop 29: iinc 3, 1 32: goto 13 sb = new StringBuilder() for(int i = 0; i < N; i++) { sb.append(OTHER_STR); } str = sb.toString(); StringBuilder
  • 157. Object creation: StringBuilder sb = new StringBuilder(); for(int i = 0; i < N; i++) { sb.append(OTHER_STR); } str = sb.toString(); StringBuilder
  • 158. String concatenation Use StringBuilder (properly) as much as possible. StringBuffer is the thread safe implementation.
  • 159. Strings in case statements
  • 160. public void taskStateMachine(String status) { switch(status) { case "PENDING": System.out.println("Status pending"); break; case "EXECUTING": System.out.println("Status executing"); break; } }
  • 163. Code optimization example: yuv2rgb converter. Always measure!
  • 166. Slightly optimized version precalc tables, fixed point operations, 2 pixels per loop…
  • 169. Lets compare: Normal, minified, minified with optimizations & jack Minified = obfuscated using Proguard
  • 170. Normal Minified Minified & optimized Jack 0 2000 4000 6000 8000 10000 12000 14000 16000 18000 20000 non-optimized optimized
  • 172. Tooling Java • javap -c <classfile> Android: •Dexdump -d <dexfile>
  • 174. Tooling – Disassembler - ART adb pull /data/dalvik- cache/arm/data@app@<package>- 1@base apk@classes.dex adb shell oatdump --oat-file=/data/dalvik- cache/arm/data@app@<package>- 1@base.apk@classes.dex
  • 175. 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 by @alblue http://alblue.bandlem.com/2016/09/javaone-hotspot.html
  • 176. Additional References Sinking your teeth into bytecode by @jakewharton http://jakewharton.com/sinking-your-teeth-into-bytecode/ Exploring Kotlin’s hidden costs by @BladeCoder https://medium.com/@BladeCoder/exploring-kotlins- hidden-costs-part-1-fbb9935d9b62
  • 177. Performance measurements Avoid doing multiple tests in one run JIT might be evil!