4Developers 2015: Czterej jeźdźcy apokalipsy, gdy Armagedon w JVM nadchodzi. - Jarosław Pałka

70
Czterej jeźdźcy apokalipsy gdy Armagedon w JVM nadchodzi.

Transcript of 4Developers 2015: Czterej jeźdźcy apokalipsy, gdy Armagedon w JVM nadchodzi. - Jarosław Pałka

Czterej jeźdźcy apokalipsy gdy Armagedon w JVM nadchodzi.

• chief architect @ Lumesse• owner/founder/one man orchestra @

symentis.pl• blogger @ geekyprimitives.wordpress.com• philosopher @ twitter:j_palka• code mangler @ bitbucket:kcrimson &

github:jpalka• evil emperor @ 4developers conf/architecture

track• restrained Padawan @ church of JVM

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

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

Moją opowieść będę snuł wokół OpenJDK 8

isystemu operacyjnego Linux

Część z tych rzeczy może być prawdą dla innych

JDK i OS

Ale niekoniecznie :)

Opowieść czas zacząć

Pewnego pięknego zimowego wieczorugdzieś w Krakowie, kilka lat temu

O godzinie 4.03Gdy nadzieja już dawno opuściła biuro

A zdrowy rozsądek już dawno wyskoczył za okno

hg clone http://hg.openjdk.java.net/jdk8/jdk8

apt-get install sysstat

apt-get install strace

apt-get install sysdig

sar -d -R 1strace -f -T -p666

A mówiła mama nie zaglądać za zamknięte drzwi?

gdywtem,nagle

iznienacka ...

Z pyłu, sadzy

i dymu, pierwszy jeździec się wyłonił

A imię jego

Garbage Collector

Wiele zrobiono i napisano o automatycznymzarządzaniu pamięcią w JVM

Gdy już ustawisz wszystkie parametryi

przełączniki A

GC nadal będzie zniewalało twój CPU

Jedyne co pozostaje to „off heap memory”

java.nio.ByteBuffer.allocateDirect()

„may reside outside of garbage collected heap”So called C-heap

Makes famous sun.misc.Unsafe a little bit saferAnd slower:)

But let's talk aboutsun.misc.Unsafe.allocateMemory

Allocation and deallocation is really expensive

Mostly because of costly JNI calls

and NMT (native memory tracking)

Mail thread@hotspot-devUnsafe allocate

Calls OS malloc functionhotspot/src/share/vm/prims/unsafe.cpp

UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory(JNIEnv *env, jobject unsafe, jlong size)) UnsafeWrapper("Unsafe_AllocateMemory"); size_t sz = (size_t)size; if (sz != (julong)size || size < 0) { THROW_0(vmSymbols::java_lang_IllegalArgumentException()); } if (sz == 0) { return 0; } sz = round_to(sz, HeapWordSize); void* x = os::malloc(sz); if (x == NULL) { THROW_0(vmSymbols::java_lang_OutOfMemoryError()); } //Copy::fill_to_words((HeapWord*)x, sz / HeapWordSize); return addr_to_java(x);UNSAFE_END

Because it uses mallocYou 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

Tools to play withgithub:alexkasko/unsafe-tools

github:peter-lawrey/Java-Chronicleapache-directmemory

Who depends on unsafeehcache (with BigMemory)

hazelcast (with ElasticMemory)infinispan

lucenecassandra

Trade offs, stupid!

Huge,really huge,

Tottaly hugedata structures

Beware!!!lifetime of objects

serialization/deserialization

… and then Jigsaw cameAnd changed the game

C-Heap APIbecause

people are actually using it(broken window)

Unsafe at any SpeedPublic sun.misc.Unsafe Replacement API

No plans for JDK9 so far

I ziemia się rozstąpiłaI ogień piekielny z ziemi wypełzać począł

drugi jeździec się wyłoniłA imię jego

Input / Output

Block deviceDevice driver

IO scheduler (merge/sort)

I/O request

%iowaitDevice queue size

Time spent on the queue

iostat ­x ­d sda 1

avgqu­sz average queue length for this device

awaitaverage response time (ms) of IO requests to a

device.

svctimaverage time (ms) a device was servicing requests.

qutim = await ­ svctim 

qutim

Czas który JVM traci na oczekiwanie na operacje IO

select() (POSIX)epoll() (Linux)kqueue (*BSD)/dev/poll

syscallrequests a service from

kernel

userspacekernelspace

CPU privileged mode

glibc

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();

java.nio

Event loops

Reactor pattern

Nie bądź głupiUżyj

netty.io

Bufory IO pomiędzykernel space

Iuser space

Operacje IO wymagają wielu operacjiKopiowania pomiędzy userspace i kernelspace

DMAmmap()

MMU

Here was slide about

Memory mapped files & page faults,

But somebody removed it :)

… and here was slide about

Vectored IO

But somebody else removed it :)

kernel-user space „zero copy”

FileChannel#transferTo()

wewnątrz JVM „zero copy”

użyj Netty, serio

CompositeByteBuf

Trade offs, stupid!

Blokować?

Nie blokuj gdy,Dużo klientów masz

Blokuj gdy,Strumienie przetwarzasz

CPUs and hard drives are really good at

sequential reading/writing

Use it

I grom potężny pazurem swym nieboskłon na strzępy rozdarł

trzeci jeździec się wyłoniłA imię jego

synchronized

Z pozoru wszystko wygląda niewinnie

%systemContext switches

Voluntary (IO wait, syscall*) Non voluntary (within time slice)

pidstat ­w ­t ­I ­p {pid}jstack {pid}

WaitingIs

waste

Non blocking algorithms

Wait-freedomKażda operacja zakończy się w z góry określonej

ilości kroków/ instrukcji

Lock-freedomPozwala na zagłodzienie wybranych wątków, Przynajmniej jeden wątek wykonuje operacje

Obstruction-freedom (optimistic concurrency)

Compare-and-swap

java.util.concurrent.atomic

„transakcyjne” metodyCopy on write

Persistent data structures

Atomic operations are

getting faster and fasterWith every new CPU

But we are not there yet!

I wody z oceanów wystąpiły, A z nich bestie żarłoczne,

Człowiekowi nieprzychylneczwarty jeździec się wyłonił

A imię jego

Just In Time compiler

Adaptive runtime

Based on profiling dataSlower startup times

Slower peek peformance(in some cases*)

JIT (Just in Time)HotSpot

Vs

AOT (Ahead of Time)(www.excelsiorjet.com)

Interpreter

C1 compiler

C2 compiler

OSR (on stack replacement)

deoptimization

Inlining

mother of all optimizations

C1 compilerinlines small methods

-XX:MaxInlineSize=35-XX:InlineSmallCode=2000

C2 compilerinlines „hot” methods

-XX:FreqInlineSize=325

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); }

}

The easy part

private, static and final

The hard part

Polimorphism

Class hierarchy analisys

Deoptimization

Beware of megamorph

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;}

Inline cache

Inline depth

Recursive inline

other optimizations

remove redundant loads

loop unrollling

global value numbering

intrinsic

escape analisys

… And few others even more interesting

lock elision

lock coarsenning

adaptive locking

biased locking

But first few words about

„fat”

and

„thin” locks

JVM uses futexA „mostly” userspace lock

based on atomic value and wait queue

Unless

high contentionwhich forces futex

to use kernelspacemutex

WAT?

Daleko jeszcze?

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

Let the eternal stream of byte codeFlows through your body