SlideShare une entreprise Scribd logo
1  sur  173
@rrafols
the bytecode
mumbo-jumbo
#perfmatters
@rrafols
Disclaimer:
This presentation contains
bytecode
Content is my own experimentation and
might differ on other environments
@rrafols
Competitions
Work
2015 Local winner
2016+ Ambassador
Runner up
Demoscene
Speaker
Author Entrepreneurship
@rrafols
Our friend the java
compiler.
@rrafols
*.java → [javac] → *.class
@rrafols
Or, for example, on
Android
@rrafols
*.java → [javac] → *.class
*.class → [dx] → dex file
@rrafols
*.java → [javac] → *.class
*.class → [dx] → dex
dex → [dexopt] → opt. dex
dex → [dex2oat] → native
@rrafols
but change is coming!
Jack & Jill
@rrafols
but change is coming!
Jack & Jill
@rrafols
*.java → [jack] → dex file
@rrafols
Let’s focus on javac
Javac vs other compilers
@rrafols
Compilers
Produces optimized code
for the target platform
@rrafols
javac
Does not produce
optimized code*
@rrafols
javac
Does not know on which
architecture the code will
be executed
@rrafols
Source: Oracle
@rrafols
For this reason
Java bytecode &
operations are stack
based
@rrafols
Easy to interpret
But not the most
performant solution
@rrafols
Quick example
Stack based integer
addition
@rrafols
j = j + i
@rrafols
Java bytecode
@rrafols
iload_3
iload_2
iadd
istore_2
@rrafols
Register based approach
@rrafols
add r01, r02, r01
or
add eax, ebx
@rrafols
Let’s make things
interesting…
j = j + i + k + w + h * 2 + p * p;
@rrafols
Java bytecode
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
Register based approach
@rrafols
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
@rrafols
Java VM (JVM)
Only the JVM knows the
architecture where is running.
In this case, for example, we used up to
8 registers
@rrafols
Java VM (JVM)
All optimizations are left to
be done by the JVM
@rrafols
Maybe takes this concept
a bit too far...
@rrafols
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);
}
@rrafols
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
@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
...
@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("%dn", b);
}
@rrafols
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
@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 15
5: iload_1
6: iadd
7: bipush 6
9: iadd
10: istore_2
@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);
}
@rrafols
javac
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
public static void main(String args[]) {
int a = 10;
int b = a + 1 + 2 + 3 + 4 + 5 + 6;
System.out.println(b);
}
@rrafols
On Android there is jack
to the rescue...
@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 31
2: sget-object v1,
Ljava/lang/System;
4: invoke-virtual {v1, v0}
7: return-void
...
@rrafols
And on Java there is the
JIT compiler to the rescue
@rrafols
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
@rrafols
Language additions
Thinks to consider
@rrafols
Autoboxing
Transparent to the developer
but compiler adds some
'extra' code
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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:
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
Autoboxing
Long total = 0;
for(Integer i = 0; i < N; i++) {
total += i;
}
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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())
}
@rrafols
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())
}
@rrafols
Autoboxing
What about Jack?
@rrafols
Autoboxing
Jack does not help in this
situation
@rrafols
Autoboxing
What about the JIT compiler?
@rrafols
Autoboxing
Let's run that loop
N times
(on my desktop computer)
N = 10.000.000.000
@rrafols
Autoboxing
@rrafols
Autoboxing
Let’s try it on Android
Dalvik VM & ART
@rrafols
Autoboxing
@rrafols
Language Additions
Use them wisely!
@rrafols
Sorting
No bytecode mumbo-jumbo
here
@rrafols
Let's sort some numbers…
Arrays.sort(...)
@rrafols
Difference between sorting
primitive types & objects
@rrafols
Using int & Integer
@rrafols
Sorting objects is a stable
sort
Default java algorithm:
TimSort adaptation
@rrafols
Sorting primitives does not
require to be stable sort
Default java algorithm:
Dual-Pivot quicksort
@rrafols
Sorting
Use primitive types as much
as possible
@rrafols
Loops
What is going on behind the
scenes
@rrafols
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;
}
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
Loops - foreach
ArrayList<Integer> list = new …
static long loopForeachList() {
long result = 0;
for(int v : list) {
result += v;
}
return result;
}
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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;
}
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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;
}
@rrafols
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
@rrafols
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
@rrafols
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;
}
@rrafols
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
@rrafols
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
@rrafols
@rrafols
@rrafols
Loops – foreach II
static long loopForeachArray(int[] array) {
long result = 0;
for(int v : array) {
result += v;
}
return result;
}
@rrafols
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 -
@rrafols
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 -
@rrafols
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 -
@rrafols
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 -
@rrafols
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 -
@rrafols
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 -
@rrafols
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 -
@rrafols
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 -
@rrafols
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 -
@rrafols
@rrafols
@rrafols
Loops
Use arrays instead of lists
@rrafols
Loops
When using lists, avoid foreach
or iterator constructions if
performance is a requirement
@rrafols
Manual bytecode
optimization
Worth it?
@rrafols
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
@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_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
-
-
-
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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[index]
-
Manual bytecode optimization
@rrafols
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[index]
-
-
Manual bytecode optimization
@rrafols
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[index]
-
-
Manual bytecode optimization
@rrafols
@rrafols
Worth it?
Only in very specific, rare, unique,
special, peculiar cases.
Too much effort involved.
@rrafols
Calling a method
Is there an overhead?
@rrafols
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
@rrafols
@rrafols
String concatenation
The evil + sign
@rrafols
String concatenation
String str = "";
for(int i = 0; i < N; i++) {
str += OTHER_STR;
}
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
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
@rrafols
String concatenation
alternatives
@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);
}
@rrafols
String.concat()
Object creation:
String str = "";
for(int i = 0; i < N; i++) {
str = str.concat(OTHER_STR);
}
@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();
@rrafols
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
@rrafols
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
@rrafols
Object creation:
StringBuilder sb = new StringBuilder();
for(int i = 0; i < N; i++) {
sb.append(OTHER_STR);
}
str = sb.toString();
StringBuilder
@rrafols
String concatenation
Use StringBuilder (properly) as
much as possible. StringBuffer
is the thread safe
implementation.
@rrafols
Strings in case statements
@rrafols
public void taskStateMachine(String status) {
switch(status) {
case "PENDING":
System.out.println("Status pending");
break;
case "EXECUTING":
System.out.println("Status executing");
break;
}
}
@rrafols
@rrafols
@rrafols
Tooling
@rrafols
Tooling - Disassembler
Java
• javap -c <classfile>
Android:
•Dexdump -d <dexfile>
@rrafols
Tooling - Assembler
Krakatau
https://github.com/Storyyeller/Krakatau
@rrafols
Tooling – Disassembler - ART
adb pull /data/dalvik-
cache/arm/data@app@<package>-1@base
apk@classes.dex
gobjdump -D <file>
@rrafols
Tooling – Disassembler - ART
adb shell oatdump --oat-file=/data/dalvik-
cache/arm/data@app@<package>-
1@base.apk@classes.dex
@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
http://alblue.bandlem.com/2016/09/javaone-hotspot.html
@rrafols
Always measure
example - yuv2rgb
optimization
@rrafols
Source: Wikipedia
@rrafols
@rrafols
Slightly optimized version
precalc tables, fixed point
operations, 2 pixels per loop…
@rrafols
@rrafols
@rrafols
Lets compare:
Normal, minified, minified
with optimizations & jack
Minified = obfuscated using Proguard
@rrafols
Normal Minified Minified & optimized Jack
0
2000
4000
6000
8000
10000
12000
14000
16000
18000
20000
non-optimized
optimized
@rrafols
Performance measurements
Avoid doing multiple tests in one run
JIT might be evil!
@rrafols
Thank you!
http://blog.rafols.org
@rrafols
https://es.linkedin.com/in/raimonrafols

Contenu connexe

Tendances

BlueHat Seattle 2019 || Don't forget to SUBSCRIBE.
BlueHat Seattle 2019 || Don't forget to SUBSCRIBE.BlueHat Seattle 2019 || Don't forget to SUBSCRIBE.
BlueHat Seattle 2019 || Don't forget to SUBSCRIBE.BlueHat Security Conference
 
掀起 Swift 的面紗
掀起 Swift 的面紗掀起 Swift 的面紗
掀起 Swift 的面紗Pofat Tseng
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerAndrey Karpov
 
Best Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesBest Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesAndrey Karpov
 
Network lab manual
Network lab manualNetwork lab manual
Network lab manualPrabhu D
 
Trying to learn C# (NDC Oslo 2019)
Trying to learn C# (NDC Oslo 2019)Trying to learn C# (NDC Oslo 2019)
Trying to learn C# (NDC Oslo 2019)Patricia Aas
 
Network lap pgms 7th semester
Network lap pgms 7th semesterNetwork lap pgms 7th semester
Network lap pgms 7th semesterDOSONKA Group
 
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
 
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
 
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
 
Exploring the x64
Exploring the x64Exploring the x64
Exploring the x64FFRI, Inc.
 
深入淺出C語言
深入淺出C語言深入淺出C語言
深入淺出C語言Simen Li
 
Tuga IT 2018 Summer Edition - The Future of C#
Tuga IT 2018 Summer Edition - The Future of C#Tuga IT 2018 Summer Edition - The Future of C#
Tuga IT 2018 Summer Edition - The Future of C#Paulo Morgado
 
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
 
Digital system design practical file
Digital system design practical fileDigital system design practical file
Digital system design practical fileArchita Misra
 
A Replay Approach to Software Validation
A Replay Approach to Software ValidationA Replay Approach to Software Validation
A Replay Approach to Software ValidationJames Pascoe
 
C++17 std::filesystem - Overview
C++17 std::filesystem - OverviewC++17 std::filesystem - Overview
C++17 std::filesystem - OverviewBartlomiej Filipek
 

Tendances (20)

BlueHat Seattle 2019 || Don't forget to SUBSCRIBE.
BlueHat Seattle 2019 || Don't forget to SUBSCRIBE.BlueHat Seattle 2019 || Don't forget to SUBSCRIBE.
BlueHat Seattle 2019 || Don't forget to SUBSCRIBE.
 
掀起 Swift 的面紗
掀起 Swift 的面紗掀起 Swift 的面紗
掀起 Swift 的面紗
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
 
ROP
ROPROP
ROP
 
Best Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesBest Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' Mistakes
 
Network lab manual
Network lab manualNetwork lab manual
Network lab manual
 
Trying to learn C# (NDC Oslo 2019)
Trying to learn C# (NDC Oslo 2019)Trying to learn C# (NDC Oslo 2019)
Trying to learn C# (NDC Oslo 2019)
 
Network lap pgms 7th semester
Network lap pgms 7th semesterNetwork lap pgms 7th semester
Network lap pgms 7th semester
 
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
 
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
 
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
 
Exploring the x64
Exploring the x64Exploring the x64
Exploring the x64
 
深入淺出C語言
深入淺出C語言深入淺出C語言
深入淺出C語言
 
Tuga IT 2018 Summer Edition - The Future of C#
Tuga IT 2018 Summer Edition - The Future of C#Tuga IT 2018 Summer Edition - The Future of C#
Tuga IT 2018 Summer Edition - The Future of C#
 
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
 
Digital system design practical file
Digital system design practical fileDigital system design practical file
Digital system design practical file
 
A Replay Approach to Software Validation
A Replay Approach to Software ValidationA Replay Approach to Software Validation
A Replay Approach to Software Validation
 
C++ Core Guidelines
C++ Core GuidelinesC++ Core Guidelines
C++ Core Guidelines
 
Tiramisu概要
Tiramisu概要Tiramisu概要
Tiramisu概要
 
C++17 std::filesystem - Overview
C++17 std::filesystem - OverviewC++17 std::filesystem - Overview
C++17 std::filesystem - Overview
 

Similaire à The bytecode mumbo-jumbo

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
 
Performance #5 cpu and battery
Performance #5  cpu and batteryPerformance #5  cpu and battery
Performance #5 cpu and batteryVitali Pekelis
 
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
 
Ilfak Guilfanov - Decompiler internals: Microcode [rooted2018]
Ilfak Guilfanov - Decompiler internals: Microcode [rooted2018]Ilfak Guilfanov - Decompiler internals: Microcode [rooted2018]
Ilfak Guilfanov - Decompiler internals: Microcode [rooted2018]RootedCON
 
Introduction to Debuggers
Introduction to DebuggersIntroduction to Debuggers
Introduction to DebuggersSaumil Shah
 
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
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesGanesh Samarthyam
 
05 - Bypassing DEP, or why ASLR matters
05 - Bypassing DEP, or why ASLR matters05 - Bypassing DEP, or why ASLR matters
05 - Bypassing DEP, or why ASLR mattersAlexandre Moneger
 
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
 
A CTF Hackers Toolbox
A CTF Hackers ToolboxA CTF Hackers Toolbox
A CTF Hackers ToolboxStefan
 
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
 
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
 
The true story_of_hello_world
The true story_of_hello_worldThe true story_of_hello_world
The true story_of_hello_worldfantasy zheng
 
LISA QooxdooTutorial Slides
LISA QooxdooTutorial SlidesLISA QooxdooTutorial Slides
LISA QooxdooTutorial SlidesTobias Oetiker
 
The n00bs guide to ovs dpdk
The n00bs guide to ovs dpdkThe n00bs guide to ovs dpdk
The n00bs guide to ovs dpdkmarkdgray
 
Open source report writing tools for IBM i Vienna 2012
Open source report writing tools for IBM i  Vienna 2012Open source report writing tools for IBM i  Vienna 2012
Open source report writing tools for IBM i Vienna 2012COMMON Europe
 

Similaire à The bytecode mumbo-jumbo (20)

Improving Java performance at JBCNConf 2015
Improving Java performance at JBCNConf 2015Improving Java performance at JBCNConf 2015
Improving Java performance at JBCNConf 2015
 
Performance #5 cpu and battery
Performance #5  cpu and batteryPerformance #5  cpu and battery
Performance #5 cpu and battery
 
Improving Android Performance at Mobiconf 2014
Improving Android Performance at Mobiconf 2014Improving Android Performance at Mobiconf 2014
Improving Android Performance at Mobiconf 2014
 
Ilfak Guilfanov - Decompiler internals: Microcode [rooted2018]
Ilfak Guilfanov - Decompiler internals: Microcode [rooted2018]Ilfak Guilfanov - Decompiler internals: Microcode [rooted2018]
Ilfak Guilfanov - Decompiler internals: Microcode [rooted2018]
 
Introduction to Debuggers
Introduction to DebuggersIntroduction to Debuggers
Introduction to Debuggers
 
Boosting Developer Productivity with Clang
Boosting Developer Productivity with ClangBoosting Developer Productivity with Clang
Boosting Developer Productivity with Clang
 
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
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java Bytecodes
 
05 - Bypassing DEP, or why ASLR matters
05 - Bypassing DEP, or why ASLR matters05 - Bypassing DEP, or why ASLR matters
05 - Bypassing DEP, or why ASLR matters
 
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]
 
A CTF Hackers Toolbox
A CTF Hackers ToolboxA CTF Hackers Toolbox
A CTF Hackers Toolbox
 
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
 
CompilersAndLibraries
CompilersAndLibrariesCompilersAndLibraries
CompilersAndLibraries
 
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
 
Staging driver sins
Staging driver sinsStaging driver sins
Staging driver sins
 
The true story_of_hello_world
The true story_of_hello_worldThe true story_of_hello_world
The true story_of_hello_world
 
LISA QooxdooTutorial Slides
LISA QooxdooTutorial SlidesLISA QooxdooTutorial Slides
LISA QooxdooTutorial Slides
 
The n00bs guide to ovs dpdk
The n00bs guide to ovs dpdkThe n00bs guide to ovs dpdk
The n00bs guide to ovs dpdk
 
LLVM Overview
LLVM OverviewLLVM Overview
LLVM Overview
 
Open source report writing tools for IBM i Vienna 2012
Open source report writing tools for IBM i  Vienna 2012Open source report writing tools for IBM i  Vienna 2012
Open source report writing tools for IBM i Vienna 2012
 

Plus de 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
 

Plus de 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 mumbo-jumbo

  • 2. @rrafols Disclaimer: This presentation contains bytecode Content is my own experimentation and might differ on other environments
  • 3. @rrafols Competitions Work 2015 Local winner 2016+ Ambassador Runner up Demoscene Speaker Author Entrepreneurship
  • 4. @rrafols Our friend the java compiler.
  • 7. @rrafols *.java → [javac] → *.class *.class → [dx] → dex file
  • 8. @rrafols *.java → [javac] → *.class *.class → [dx] → dex dex → [dexopt] → opt. dex dex → [dex2oat] → native
  • 9. @rrafols but change is coming! Jack & Jill
  • 10. @rrafols but change is coming! Jack & Jill
  • 12. @rrafols Let’s focus on javac Javac vs other compilers
  • 15. @rrafols javac Does not know on which architecture the code will be executed
  • 17. @rrafols For this reason Java bytecode & operations are stack based
  • 18. @rrafols Easy to interpret But not the most performant solution
  • 24. @rrafols add r01, r02, r01 or add eax, ebx
  • 25. @rrafols Let’s make things interesting… j = j + i + k + w + h * 2 + p * p;
  • 27. @rrafols 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
  • 28. @rrafols 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
  • 29. @rrafols 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. @rrafols 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. @rrafols 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. @rrafols 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. @rrafols 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. @rrafols 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
  • 36. @rrafols Java VM (JVM) Only the JVM knows the architecture where is running. In this case, for example, we used up to 8 registers
  • 37. @rrafols Java VM (JVM) All optimizations are left to be done by the JVM
  • 38. @rrafols Maybe takes this concept a bit too far...
  • 39. @rrafols 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); }
  • 40. @rrafols 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
  • 41. @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 ...
  • 42. @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("%dn", b); }
  • 43. @rrafols 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
  • 44. @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 15 5: iload_1 6: iadd 7: bipush 6 9: iadd 10: istore_2
  • 45. @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); }
  • 46. @rrafols javac 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 public static void main(String args[]) { int a = 10; int b = a + 1 + 2 + 3 + 4 + 5 + 6; System.out.println(b); }
  • 47. @rrafols On Android there is jack to the rescue...
  • 48. @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 31 2: sget-object v1, Ljava/lang/System; 4: invoke-virtual {v1, v0} 7: return-void ...
  • 49. @rrafols And on Java there is the JIT compiler to the rescue
  • 50. @rrafols 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
  • 52. @rrafols Autoboxing Transparent to the developer but compiler adds some 'extra' code
  • 53. @rrafols 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
  • 54. @rrafols 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
  • 55. @rrafols 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
  • 56. @rrafols 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:
  • 57. @rrafols 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. @rrafols 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. @rrafols 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. @rrafols Autoboxing Long total = 0; for(Integer i = 0; i < N; i++) { total += i; }
  • 61. @rrafols 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
  • 62. @rrafols 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
  • 63. @rrafols 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
  • 64. @rrafols 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
  • 65. @rrafols 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. @rrafols 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. @rrafols 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. @rrafols 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
  • 69. @rrafols 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()) }
  • 70. @rrafols 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()) }
  • 72. @rrafols Autoboxing Jack does not help in this situation
  • 74. @rrafols Autoboxing Let's run that loop N times (on my desktop computer) N = 10.000.000.000
  • 76. @rrafols Autoboxing Let’s try it on Android Dalvik VM & ART
  • 80. @rrafols Let's sort some numbers… Arrays.sort(...)
  • 83. @rrafols Sorting objects is a stable sort Default java algorithm: TimSort adaptation
  • 84. @rrafols Sorting primitives does not require to be stable sort Default java algorithm: Dual-Pivot quicksort
  • 86. @rrafols Loops What is going on behind the scenes
  • 87. @rrafols 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; }
  • 88. @rrafols 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
  • 89. @rrafols 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
  • 90. @rrafols 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
  • 91. @rrafols 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
  • 92. @rrafols Loops - foreach ArrayList<Integer> list = new … static long loopForeachList() { long result = 0; for(int v : list) { result += v; } return result; }
  • 93. @rrafols 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
  • 94. @rrafols 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
  • 95. @rrafols 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
  • 96. @rrafols 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; }
  • 97. @rrafols 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
  • 98. @rrafols 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
  • 99. @rrafols 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
  • 100. @rrafols 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; }
  • 101. @rrafols 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
  • 102. @rrafols 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
  • 103. @rrafols 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; }
  • 104. @rrafols 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
  • 105. @rrafols 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
  • 108. @rrafols Loops – foreach II static long loopForeachArray(int[] array) { long result = 0; for(int v : array) { result += v; } return result; }
  • 109. @rrafols 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 -
  • 110. @rrafols 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 -
  • 111. @rrafols 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 -
  • 112. @rrafols 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 -
  • 113. @rrafols 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 -
  • 114. @rrafols 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 -
  • 115. @rrafols 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 -
  • 116. @rrafols 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 -
  • 117. @rrafols 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 -
  • 121. @rrafols Loops When using lists, avoid foreach or iterator constructions if performance is a requirement
  • 123. @rrafols 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
  • 124. @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_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 - - -
  • 125. @rrafols 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
  • 126. @rrafols 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
  • 127. @rrafols 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
  • 128. @rrafols 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[index] - Manual bytecode optimization
  • 129. @rrafols 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[index] - - Manual bytecode optimization
  • 130. @rrafols 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[index] - - Manual bytecode optimization
  • 132. @rrafols Worth it? Only in very specific, rare, unique, special, peculiar cases. Too much effort involved.
  • 133. @rrafols Calling a method Is there an overhead?
  • 134. @rrafols 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
  • 137. @rrafols String concatenation String str = ""; for(int i = 0; i < N; i++) { str += OTHER_STR; }
  • 138. @rrafols 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
  • 139. @rrafols 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
  • 140. @rrafols 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
  • 141. @rrafols 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
  • 142. @rrafols 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
  • 143. @rrafols 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. @rrafols 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
  • 145. @rrafols 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
  • 147. @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); }
  • 148. @rrafols String.concat() Object creation: String str = ""; for(int i = 0; i < N; i++) { str = str.concat(OTHER_STR); }
  • 149. @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();
  • 150. @rrafols 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
  • 151. @rrafols 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
  • 152. @rrafols Object creation: StringBuilder sb = new StringBuilder(); for(int i = 0; i < N; i++) { sb.append(OTHER_STR); } str = sb.toString(); StringBuilder
  • 153. @rrafols String concatenation Use StringBuilder (properly) as much as possible. StringBuffer is the thread safe implementation.
  • 155. @rrafols public void taskStateMachine(String status) { switch(status) { case "PENDING": System.out.println("Status pending"); break; case "EXECUTING": System.out.println("Status executing"); break; } }
  • 159. @rrafols Tooling - Disassembler Java • javap -c <classfile> Android: •Dexdump -d <dexfile>
  • 161. @rrafols Tooling – Disassembler - ART adb pull /data/dalvik- cache/arm/data@app@<package>-1@base apk@classes.dex gobjdump -D <file>
  • 162. @rrafols Tooling – Disassembler - ART adb shell oatdump --oat-file=/data/dalvik- cache/arm/data@app@<package>- 1@base.apk@classes.dex
  • 163. @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 http://alblue.bandlem.com/2016/09/javaone-hotspot.html
  • 164. @rrafols Always measure example - yuv2rgb optimization
  • 167. @rrafols Slightly optimized version precalc tables, fixed point operations, 2 pixels per loop…
  • 170. @rrafols Lets compare: Normal, minified, minified with optimizations & jack Minified = obfuscated using Proguard
  • 171. @rrafols Normal Minified Minified & optimized Jack 0 2000 4000 6000 8000 10000 12000 14000 16000 18000 20000 non-optimized optimized
  • 172. @rrafols Performance measurements Avoid doing multiple tests in one run JIT might be evil!