Jarosław Pałka
Language: Polish
JVM towarzyszy mi w projektach od prawie 15 lat. Łączą nas dobre chwile i złe wspomnienia, którymi będę się chciał z wami podzielić. Opowiem o 4 jeźdźcach apokalipsy którzy zamieszkują maszynę wirtualną i od czasu do czas dają znać o swojej obecności. Podstępnie zakradają się do zakamarków waszego systemu operacyjnego, procesorów i obszarów pamięci RAM, powodując że wasza aplikacja na produkcji zachowuje się jak wygłodniałe acz powolne zombie.
Kim są Ci odrażający jeźdźcy? To GC, operacje I/O, wątki i interpretowany bytecode. Postaram się na przykładach pokazać narzędzia dostępne w JDK jak i w waszym systemie operacyjnym, które pozwolą wam rozpoznać z którym z nich macie do czynienia a także techniki radzenia sobie z spadkiem wydajności. Prezentacja będzie pokazywać ekstremalne przypadki, które wymagać będą nietypowych technik, jednak wszystko odbędzie się zgodnie z zasadami sztuki a pokazane rozwiązania oparte będą na API i technikach dostępnym w każdym JDK.
Więc o czym tak naprawdę będzie?
Usłyszycie słów kilka o "off-heap memory", gdy wszystkie rozsądne techniki optymalizacji GC zawiodły.
A także o "non-blocking IO" i "zero-copy buffers", gdy już klasyczne IO zawiodło.
Nie obędzie się bez łagodnego wstępu do java.util.concurrent.atomic.* i "lock free programming", gdy już nie radzicie sobie z ilością wątków.
A na koniec opowiem o "just-in time compilation" i jak pisać kod, który jest "JIT friendly".
To wszystko i więcej o wydajności i optymalizacji JVM, dla waszej radości i uciechy przyszłych pokoleń.
4. Celem tej prezentacji jest pokazanie
Technik, których na co dzień nie będziecie
Stosować
Ten materiał zakłada, że na co dzień nie
zgłębiacie terenów przygranicznych
System operacyjny/maszyna wirtualna
Zaprezentowane poniżej informacje i fakty
mogą trwale odmienić wasze postrzeganie
rzeczywistości
5. Dopiero zaczynasz z JVM?
Zachwycisz się złożonością
Masz już za sobą pierwszy pad produkcji?
Przeklniesz złożoność JVM
Chcesz wiedzieć więcej jak to wszystko
działa?
Ta prezentacja łagodnie wprowadzi Cię w
terminologię i podstawy
6. Moją opowieść będę snuł wokół
OpenJDK 8
i
systemu operacyjnego Linux
Część z tych rzeczy może być
prawdą dla innych
JDK i OS
17. Wiele zrobiono i napisano o automatycznym
zarządzaniu pamięcią w JVM
Gdy już ustawisz wszystkie parametry
i
przełączniki
A
GC nadal będzie zniewalało twój CPU
Jedyne co pozostaje to „off heap memory”
19. Allocation and deallocation
is really expensive
Mostly because of costly
JNI calls
and
NMT (native memory tracking)
Mail thread@hotspot-dev
Unsafe allocate
Calls OS malloc function
hotspot/src/share/vm/prims/unsafe.cpp
21. Because it uses malloc
You can „easily” provide your own allocator
export LD_PRELOAD=mylib.so
jemalloc (look cassandra case)
Anyway, it all can end up with
„core dump”
So be carefull
Or use wrappers
22. Tools to play with
github:alexkasko/unsafe-tools
github:peter-lawrey/Java-Chronicle
apache-directmemory
Who depends on unsafe
ehcache (with BigMemory)
hazelcast (with ElasticMemory)
infinispan
lucene
cassandra
25. … and then Jigsaw came
And changed the game
C-Heap API
because
people are actually using it
(broken window)
Unsafe at any Speed
Public sun.misc.Unsafe Replacement API
No plans for JDK9 so far
26. I ziemia się rozstąpiła
I ogień piekielny z ziemi wypełzać począł
drugi jeździec się wyłonił
A imię jego
30. avgqusz
average queue length for this device
await
average response time (ms) of IO requests to a
device.
svctim
average time (ms) a device was servicing requests.
qutim = await svctim
35. sun.nio.ch.DefaultSelectorProvider
if ("Linux".equals(osname)) {
String osversion = AccessController.doPrivileged(
new GetPropertyAction("os.version"));
String[] vers = osversion.split(".", 0);
if (vers.length >= 2) {
try {
int major = Integer.parseInt(vers[0]);
int minor = Integer.parseInt(vers[1]);
if (major > 2 || (major == 2 && minor >= 6)) {
return new sun.nio.ch.EPollSelectorProvider();
}
} catch (NumberFormatException x) {
// format not recognized
}
}
}
return new sun.nio.ch.PollSelectorProvider();
50. Non blocking algorithms
Wait-freedom
Każda operacja zakończy się w z góry określonej
ilości kroków/ instrukcji
Lock-freedom
Pozwala na zagłodzienie wybranych wątków,
Przynajmniej jeden wątek wykonuje operacje
Obstruction-freedom (optimistic concurrency)
58. Inlining
mother of all optimizations
C1 compiler
inlines small methods
-XX:MaxInlineSize=35
-XX:InlineSmallCode=2000
C2 compiler
inlines „hot” methods
-XX:FreqInlineSize=325
59. public class Inline{
public int doubleAndSum(int x,y){
return makeDouble(x)+makeDouble(y);
}
private int makeDouble(int x){
return x+x;
}
//after inlining
public int doubleAndSum(int x,y){
return (x+x)+(y+y);
}
}
60. The easy part
private, static and final
The hard part
Polimorphism
Class hierarchy analisys
Deoptimization
Beware of megamorph
61. const char* StackWalkCompPolicy::shouldInline(methodHandle m, float freq, int cnt) {
// Allows targeted inlining
// positive filter: should send be inlined? returns NULL (--> yes)
// or rejection msg
int max_size = MaxInlineSize;
int cost = m->code_size();
// Check for too many throws (and not too huge)
if (m->interpreter_throwout_count() > InlineThrowCount && cost <
InlineThrowMaxSize ) {
return NULL;
}
// bump the max size if the call is frequent
if ((freq >= InlineFrequencyRatio) || (cnt >= InlineFrequencyCount)) {
if (TraceFrequencyInlining) {
tty->print("(Inlined frequent method)n");
m->print();
}
max_size = FreqInlineSize;
}
if (cost > max_size) {
return (_msg = "too big");
}
return NULL;
}
69. What Every Programmer Should Know About Memory
Cpu Caches and Why You Care
Lock-Free Programming (or, Juggling Razor Blades)
brain food for hackers
Linux Device Drivers