3. Krótko o mnie
●
Programuję od 1992
●
Zawodowo:
– Od 10.2006 – 08.2007 – RODO
– Od 09.2007 – Britenet sp z. o. o
Java Programmer /
Team Leader /
System Architect /
Solution Architect
21. Wstęp
●
JIT vs AOT
●
Zależy od implementacji JVM – Oracle Hotspot
●
Optymalizuje:
– Metody – ivocation counter
– Pętle – backedge counter, OSR
22. Wstęp
●
JIT vs AOT
●
Zależy od implementacji JVM – Oracle Hotspot
●
Optymalizuje:
– Metody – ivocation counter
– Pętle – backedge counter, OSR
●
Co nie jest zabronione jest dozwolone
66. Redundancy removal
●
Po co robić 2x to samo?
static class Value {
int i;
}
private Value value;
void execute() {
int j = value.i + 1;
int k = value.i + 1;
}
69. Implicit checks elimination
●
Ochrona przed zrobieniem „głupstwa”
public static int getSize(Collection collection) {
return collection.size();
}
To tak na prawdę:
public static int getSize(Collection collection) {
if (collection == null) {
throw new NullPointerException();
}
return collection.size();
}
71. Implicit checks elimination
●
Gdyby ich nie było --> crash JVM (np.
segmentation fault)
●
Optymalizacje dla
– Dobrych programistów – signal handler
72. Implicit checks elimination
●
Gdyby ich nie było --> crash JVM (np.
segmentation fault)
●
Optymalizacje dla
– Dobrych programistów – signal handler
– Gorszych programistów – check
73. Implicit checks elimination
●
Gdyby ich nie było --> crash JVM (np.
segmentation fault)
●
Optymalizacje dla
– Dobrych programistów – signal handler
– Gorszych programistów – check
– Bardzo złych programistów – exception cache
74. Implicit checks elimination
●
Gdyby ich nie było --> crash JVM (np.
segmentation fault)
●
Optymalizacje dla
– Dobrych programistów – signal handler
– Gorszych programistów – check
– Bardzo złych programistów – exception cache
●
Optymalizacja spekulatywna
91. Devirtualization – klasy – 3
static double do1(AbstractMathFunc func, double i) {
if (func.getClass().equals(SinFunc.class)) {
return Math.sin(i);
} else if (func.getClass().equals(CosFunc.class)) {
return Math.cos(i);
} else {
uncommon_trap
}
}
●
Co jeżeli jest pojawi się SqrtFunc?
92. Devirtualization – klasy – 3
static double do1(AbstractMathFunc func, double i) {
if (func.getClass().equals(SinFunc.class)) {
return Math.sin(i);
} else if (func.getClass().equals(CosFunc.class)) {
return Math.cos(i);
} else {
uncommon_trap
}
}
●
Co jeżeli jest pojawi się SqrtFunc?
●
Co jeżeli jest SqrtFunc zacznie być używane?
101. Co lubi JIT?
●
Krótkie metody
●
Zmienne lokalne
●
Niemutowalność
●
Ładny, przejrzysty kod
102. Co lubi JIT?
●
Krótkie metody
●
Zmienne lokalne
●
Niemutowalność
●
Ładny, przejrzysty kod
●
Typy prymitywne
103. Co lubi JIT?
●
Krótkie metody
●
Zmienne lokalne
●
Niemutowalność
●
Ładny, przejrzysty kod
●
Typy prymitywne
●
Abstrakcje z jedną/dwiema implementacją
104. Co lubi JIT?
●
Krótkie metody
●
Zmienne lokalne
●
Niemutowalność
●
Ładny, przejrzysty kod
●
Typy prymitywne
●
Abstrakcje z jedną/dwiema implementacją
●
Nieprzeciążone metody
105. Jaki kod lubi JIT?
void execute() {
// ... some logic
int result = send();
if (result < 0) {
// handle error
// ... very long logic
}
}
106. Jaki kod lubi JIT?
void execute() {
// ... some logic
int result = send();
if (result < 0) {
// handle error
handleError();
}
}
107. Konsekwencje
●
Możliwe fazy stop the world
●
Exception cache
●
Kod ma znaczenie
●
Składnia vs wydajność,
struktury danych vs wydajność
109. Wydajność
Programmers waste enormous amounts of time thinking
about, or worrying about, the speed of noncritical parts
of their programs, and these attempts at efficiency
actually have a strong negative impact when debugging
and maintenance are considered. We should forget
about small efficiencies, say about 97% of the time:
premature optimization is the root of all evil. Yet we
should not pass up our opportunities in that critical 3%.
Donald Knuth
111. Wydajność
Programmers waste enormous amounts of time thinking
about, or worrying about, the speed of noncritical parts
of their programs, and these attempts at efficiency
actually have a strong negative impact when debugging
and maintenance are considered. We should forget
about small efficiencies, say about 97% of the time:
premature optimization is the root of all evil. Yet we
should not pass up our opportunities in that critical 3%.
Donald Knuth
114. Konsekwencje
●
Możliwe fazy stop the world
●
Exception cache
●
Kod ma znaczenie
●
Składnia vs wydajność,
struktury danych vs wydajność
●
Restart JVM --> zaczynamy od nowa
115. Konsekwencje
●
Możliwe fazy stop the world
●
Exception cache
●
Kod ma znaczenie
●
Składnia vs wydajność,
struktury danych vs wydajność
●
Restart JVM --> zaczynamy od nowa
●
Concurrency?
120. Concurrency
An implementation is free to produce any code it likes,
as long as all resulting executions of a program produce
a result that can be predicted by the memory model.
This provides a great deal of freedom for the
implementor to perform a myriad of code
transformations, including the reordering of actions
and removal of unnecessary synchronization.
Java Language Specification (17.4)
123. Concurrency
private int i;
private int j;
private int k;
void execute() {
i = 1;
j = 2;
k = 3;
if (i > 0) {
i = k;
}
}
execute() start
i = 1
124. Concurrency
private int i;
private int j;
private int k;
void execute() {
i = 1;
j = 2;
k = 3;
if (i > 0) {
i = k;
}
}
execute() start
i = 1 k = 3
125. Concurrency
private int i;
private int j;
private int k;
void execute() {
i = 1;
j = 2;
k = 3;
if (i > 0) {
i = k;
}
}
execute() start
i = 1 k = 3 j = 2
126. Concurrency
private int i;
private int j;
private int k;
void execute() {
i = 1;
j = 2;
k = 3;
if (i > 0) {
i = k;
}
}
execute() start
i = 1 k = 3 j = 2
if (i > 0)
false true
127. Concurrency
private int i;
private int j;
private int k;
void execute() {
i = 1;
j = 2;
k = 3;
if (i > 0) {
i = k;
}
}
execute() start
i = 1 k = 3 j = 2
if (i > 0)
false true
i = k
128. Concurrency
private int i;
private int j;
private int k;
void execute() {
i = 1;
j = 2;
k = 3;
if (i > 0) {
i = k;
}
}
execute() start
i = 1 k = 3 j = 2
if (i > 0)
false true
i = k
execute() end
129. Double-checked locking
private Helper helper;
public Helper getHelper() {
if (helper == null) {
synchronized (this) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
130. Double-checked locking
private Helper helper;
public Helper getHelper() {
if (helper == null) {
synchronized (this) {
if (helper == null) {
local = calloc(sizeof(Helper.class));
local.<init>();
helper = local;
}
}
}
return helper;
}
133. Double-checked locking
synchronized (this) {
if (helper == null) {
local = c(s(Helper.class));
local.<init>();
helper = local;
}
}
synchronized() start
true
If (helper == null)
false
134. Double-checked locking
synchronized (this) {
if (helper == null) {
local = c(s(Helper.class));
local.<init>();
helper = local;
}
}
synchronized() start
true
If (helper == null)
false
local = c(s(Helper.class))
135. Double-checked locking
synchronized (this) {
if (helper == null) {
local = c(s(Helper.class));
local.<init>();
helper = local;
}
}
synchronized() start
true
If (helper == null)
false
local = c(s(Helper.class))
local.<init>()
136. Double-checked locking
synchronized (this) {
if (helper == null) {
local = c(s(Helper.class));
local.<init>();
helper = local;
}
}
synchronized() start
true
If (helper == null)
false
local = c(s(Helper.class))
local.<init>() helper = local
137. Double-checked locking
synchronized (this) {
if (helper == null) {
local = c(s(Helper.class));
local.<init>();
helper = local;
}
}
synchronized() start
true
If (helper == null)
false
local = c(s(Helper.class))
local.<init>() helper = local
synchronized() end
138. Double-checked locking
private Helper helper;
public Helper getHelper() {
if (helper == null) {
synchronized (this) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
139. Concurrency
The behavior of threads, particularly when not correctly
synchronized, can be confusing and counterintuitive.
The semantics of the Java programming language allow
compilers and microprocessors to perform optimizations
that can interact with incorrectly synchronized code in
ways that can produce behaviors that seem paradoxical.
To some programmers, this behavior may seem
"broken". However, it should be noted thatthis code is
improperly synchronize.
Java Language Specification (17 & 17.4)
144. Spec vs impl
JMM executions JMM results
BytecodeJava code
Program
JAOT compilation
145. Spec vs impl
JMM executions JMM results
BytecodeJava code
Program
JVM interpreter JVM compilationJAOT compilation
146. Spec vs impl
JMM executions JMM results
Bytecode
JVM results
Java code
Program
JVM interpreter JVM compilationJAOT compilation
147. Spec vs impl
JMM executions JMM results
Bytecode
●
JVM results to podzbiór JMM results
JVM results
Java code
Program
JVM interpreter JVM compilationJAOT compilation
148. Concurrency
An implementation is free to produce any code it likes,
as long as all resulting executions of a program
produce a result that can be predicted by the
memory model. This provides a great deal of freedom
for the implementor to perform a myriad of code
transformations, including the reordering of actions and
removal of unnecessary synchronization.
Java Language Specification (17.4)
149. JMM w pigułce – 1 / 2
●
Obiekt immutable: (Safe construction)
150. JMM w pigułce – 1 / 2
●
Obiekt immutable: (Safe construction)
– Wszystkie pola final
151. JMM w pigułce – 1 / 2
●
Obiekt immutable: (Safe construction)
– Wszystkie pola final
– Nie udostępnia samego siebie w konstruktorze
152. JMM w pigułce – 1 / 2
●
Obiekt immutable: (Safe construction)
– Wszystkie pola final
– Nie udostępnia samego siebie w konstruktorze
●
Pary synchronizacji:
153. JMM w pigułce – 1 / 2
●
Obiekt immutable: (Safe construction)
– Wszystkie pola final
– Nie udostępnia samego siebie w konstruktorze
●
Pary synchronizacji:
Send Receive
154. JMM w pigułce – 1 / 2
●
Obiekt immutable: (Safe construction)
– Wszystkie pola final
– Nie udostępnia samego siebie w konstruktorze
●
Pary synchronizacji:
Send Receive
Monitor unlock Monitor lock
155. JMM w pigułce – 1 / 2
●
Obiekt immutable: (Safe construction)
– Wszystkie pola final
– Nie udostępnia samego siebie w konstruktorze
●
Pary synchronizacji:
Send Receive
Monitor unlock Monitor lock
Volatile write Volatile read
156. JMM w pigułce – 1 / 2
●
Obiekt immutable: (Safe construction)
– Wszystkie pola final
– Nie udostępnia samego siebie w konstruktorze
●
Pary synchronizacji:
Send Receive
Monitor unlock Monitor lock
Volatile write Volatile read
Varhandle release (*) Varhandle acquire (*)
157. JMM w pigułce – 1 / 2
●
Obiekt immutable: (Safe construction)
– Wszystkie pola final
– Nie udostępnia samego siebie w konstruktorze
●
Pary synchronizacji:
Send Receive
Monitor unlock Monitor lock
Volatile write Volatile read
Varhandle release (*) Varhandle acquire (*)
Starting thread New thread started
158. JMM w pigułce – 1 / 2
●
Obiekt immutable: (Safe construction)
– Wszystkie pola final
– Nie udostępnia samego siebie w konstruktorze
●
Pary synchronizacji:
Send Receive
Monitor unlock Monitor lock
Volatile write Volatile read
Varhandle release (*) Varhandle acquire (*)
Starting thread New thread started
Terminating thread (self) Finding terminated thread
159. JMM w pigułce – 2 / 2
Write a
...
Write b
…
Write c
Thread1
Thread2
160. JMM w pigułce – 2 / 2
Write a
...
Write b
…
Write c
Send Receive
Thread1
Thread2
161. JMM w pigułce – 2 / 2
Write a
...
Write b
…
Write c
Send Receive
Read b
…
Read c
…
Read a
Thread1
Thread2
Safe
publication
162. JMM w pigułce – 2 / 2
Write a
...
Write b
…
Write c
Send Receive
Read b
…
Read c
…
Read a
Thread1
Thread2
Write a
...
Write b
…
Write c
Thread3
163. JMM w pigułce – 2 / 2
Write a
...
Write b
…
Write c
Send Receive
Read b
…
Read c
…
Read a
Thread1
Thread2
Read b
…
Read c
…
Read a
Thread4
164. JMM w pigułce – 2 / 2
Write a
...
Send Receive
...
Read a
…
Receive
…
Read aSafe
publication
Thread1
Thread2
Write a
...
Send
Thread3
165. Double-checked locking
private Helper helper;
public Helper getHelper() {
if (helper == null) {
synchronized (this) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
166. Jak zrozumieć JMM?
●
Aleksey Shipilëv:
– YouTube – GeeCON Conference – Java
Memory Model Unlearning Experience – 2-5
razy
167. Jak zrozumieć JMM?
●
Aleksey Shipilëv:
– YouTube – GeeCON Conference – Java
Memory Model Unlearning Experience – 2-5
razy
– YouTube – v JUG – Java Memory Model
Pragmatics – 2-3 razy
168. Jak zrozumieć JMM?
●
Aleksey Shipilëv:
– YouTube – GeeCON Conference – Java
Memory Model Unlearning Experience – 2-5
razy
– YouTube – v JUG – Java Memory Model
Pragmatics – 2-3 razy
●
Specyfikacja
169. Jak już musisz...
package java.util.concurrent;
package java.util.concurrent.atomic;
package java.util.concurrent.locks;
176. Konsekwencje
●
Możliwe fazy stop the world
●
Exception cache
●
Kod ma znaczenie
●
Składnia vs wydajność,
struktury danych vs wydajność
●
Restart JVM --> zaczynamy od nowa
●
Concurrency?
●
Pamięć
177. Pamięć w JVM – parallel
Heap
Young gen Old gen
Eden
Tenured
Off heap
Metaspace
Code
cache
Thread Native
S0
S1
Runtimeconstantpool
Methodbytecode
Classinfo
Programcounter
Stack
Nativestack
Nonprofiledcode
Profiledcode
Nonmethodcode
178. JIT w pamięci
Off heap
Code
cache
Heap
Young gen Old gen
Eden
Tenured
S0
S1
Metaspace Thread NativeRuntimeconstantpool
Methodbytecode
Classinfo
Programcounter
Stack
Nativestack
Nonprofiledcode
Profiledcode
Nonmethodcode
179. JIT w pamięci – arch. rozp.
Service
A (1)
Service
A (2)
Service
A (3)
Service
A (4)
Service
B (1)
Service
B (2)
Service
B (3)
Service
B (4)
Service
C (1)
Service
C (2)
Service
C (3)
Service
C (4)
Service
D (1)
Service
D (2)
Service
D (3)
Service
D (4)
194. Może coś da się zrobić?
Kompilator Sweeper
1 / 14000605
1 / 14000605
195. Sweeper – success story
●
Charakterystyka użycia kodu zmienna w czasie
196. Sweeper – success story
●
Charakterystyka użycia kodu zmienna w czasie
– Start aplikacji / późniejsze użycie
197. Sweeper – success story
●
Charakterystyka użycia kodu zmienna w czasie
– Start aplikacji / późniejsze użycie
– Inne użycie aplikacji w czasie
198. Sweeper – success story
●
Charakterystyka użycia kodu zmienna w czasie
– Start aplikacji / późniejsze użycie
– Inne użycie aplikacji w czasie
●
np. w ciągu dnia biznes, wieczorem klienci
indywidualni
199. Sweeper – success story
●
Charakterystyka użycia kodu zmienna w czasie
– Start aplikacji / późniejsze użycie
– Inne użycie aplikacji w czasie
●
np. w ciągu dnia biznes, wieczorem klienci
indywidualni
●
np. w ciągu dni aplikacja webowa, w nocy
przetwarzanie batchowe
200. Konsekwencje
●
Możliwe fazy stop the world
●
Exception cache
●
Kod ma znaczenie
●
Składnia vs wydajność,
struktury danych vs wydajność
●
Restart JVM --> zaczynamy od nowa
●
Concurrency?
●
Pamięć
●
Nowe zachowanie --> spowolnienie aplikacji
201. Konsekwencje
●
Możliwe fazy stop the world
●
Exception cache
●
Kod ma znaczenie
●
Składnia vs wydajność,
struktury danych vs wydajność
●
Restart JVM --> zaczynamy od nowa
●
Concurrency?
●
Pamięć
●
Nowe zachowanie --> spowolnienie aplikacji
●
Testy wydajnościowe
218. Czy ktoś coś z tym robi?
●
ShenandoahGC i ZGC
●
Np. optymalizacja „loop strip mining” – JDK 10 –
z bugiem :) Bug id: 8220374
219. Czy ktoś coś z tym robi?
●
ShenandoahGC i ZGC
●
Np. optymalizacja „loop strip mining” – JDK 10 –
z bugiem :) Bug id: 8220374
●
Naprawione w JDK 13 (b13) i downport do JDK
12 (u2) i JDK 11 (u4)
220. Czy ktoś coś z tym robi?
●
ShenandoahGC i ZGC
●
Np. optymalizacja „loop strip mining” – JDK 10 –
z bugiem :) Bug id: 8220374
●
Naprawione w JDK 13 (b13) i downport do JDK
12 (u2) i JDK 11 (u4)
●
Tylko dla ZGC, ShenandoahGC i G1
223. Złote rady wujka Krzyśka
●
Monitoruj Code cache
●
Używaj prymitywów
●
Zainteresuj się wydajnością aktualnie pisanego
kodu
224. Złote rady wujka Krzyśka
●
Monitoruj Code cache
●
Używaj prymitywów
●
Zainteresuj się wydajnością aktualnie pisanego
kodu
●
Używaj nowych wersji JDK
225. Złote rady wujka Krzyśka
●
Monitoruj Code cache
●
Używaj prymitywów
●
Zainteresuj się wydajnością aktualnie pisanego
kodu
●
Używaj nowych wersji JDK
●
Używaj metod synchronizacji jak najwyższego
poziomu
226. Złote rady wujka Krzyśka
●
Monitoruj Code cache
●
Używaj prymitywów
●
Zainteresuj się wydajnością aktualnie pisanego
kodu
●
Używaj nowych wersji JDK
●
Używaj metod synchronizacji jak najwyższego
poziomu
●
Koduj zgodnie ze specyfikacją, nie
implementacją
227. Złote rady wujka Krzyśka
●
Monitoruj Code cache
●
Używaj prymitywów
●
Zainteresuj się wydajnością aktualnie pisanego
kodu
●
Używaj nowych wersji JDK
●
Używaj metod synchronizacji jak najwyższego
poziomu
●
Koduj zgodnie ze specyfikacją, nie
implementacją
●
Nie rób optymalizacji które robi JIT
228. Złote rady wujka Krzyśka
●
Monitoruj Code cache
●
Używaj prymitywów
●
Zainteresuj się wydajnością aktualnie pisanego
kodu
●
Używaj nowych wersji JDK
●
Używaj metod synchronizacji jak najwyższego
poziomu
●
Koduj zgodnie ze specyfikacją, nie implementacją
●
Nie rób optymalizacji które robi JIT
●
Nie traktuj kluczowych składowych systemu jako
BlackBox