Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

606 views

Published on

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ń.

Published in: Software
  • Be the first to comment

  • Be the first to like this

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

  1. 1. Czterej jeźdźcy apokalipsy gdy Armagedon w JVM nadchodzi.
  2. 2. • 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
  3. 3. 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
  4. 4. 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
  5. 5. 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
  6. 6. Ale niekoniecznie :)
  7. 7. Opowieść czas zacząć
  8. 8. Pewnego pięknego zimowego wieczoru gdzieś w Krakowie, kilka lat temu
  9. 9. O godzinie 4.03 Gdy 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
  10. 10. apt-get install sysstat apt-get install strace apt-get install sysdig sar -d -R 1 strace -f -T -p666
  11. 11. A mówiła mama nie zaglądać za zamknięte drzwi?
  12. 12. gdy wtem, nagle i znienacka ...
  13. 13. Z pyłu, sadzy i dymu, pierwszy jeździec się wyłonił A imię jego
  14. 14. Garbage Collector
  15. 15. 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”
  16. 16. java.nio.ByteBuffer.allocateDirect() „may reside outside of garbage collected heap” So called C-heap Makes famous sun.misc.Unsafe a little bit safer And slower:) But let's talk about sun.misc.Unsafe.allocateMemory
  17. 17. 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
  18. 18. 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
  19. 19. 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
  20. 20. 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
  21. 21. Trade offs, stupid!
  22. 22. Huge, really huge, Tottaly huge data structures Beware!!! lifetime of objects serialization/deserialization
  23. 23. … 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
  24. 24. I ziemia się rozstąpiła I ogień piekielny z ziemi wypełzać począł drugi jeździec się wyłonił A imię jego
  25. 25. Input / Output
  26. 26. Block deviceDevice driver IO scheduler (merge/sort) I/O request
  27. 27. %iowait Device queue size Time spent on the queue iostat ­x ­d sda 1
  28. 28. avgqu­sz 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 
  29. 29. qutim Czas który JVM traci na oczekiwanie na operacje IO
  30. 30. select() (POSIX) epoll() (Linux) kqueue (*BSD) /dev/poll
  31. 31. syscall requests a service from kernel userspace kernelspace CPU privileged mode glibc
  32. 32. 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();
  33. 33. java.nio Event loops Reactor pattern
  34. 34. Nie bądź głupi Użyj netty.io
  35. 35. Bufory IO pomiędzy kernel space I user space Operacje IO wymagają wielu operacji Kopiowania pomiędzy userspace i kernelspace DMA mmap() MMU
  36. 36. Here was slide about Memory mapped files & page faults, But somebody removed it :)
  37. 37. … and here was slide about Vectored IO But somebody else removed it :)
  38. 38. kernel-user space „zero copy” FileChannel#transferTo() wewnątrz JVM „zero copy” użyj Netty, serio CompositeByteBuf
  39. 39. Trade offs, stupid!
  40. 40. Blokować? Nie blokuj gdy, Dużo klientów masz Blokuj gdy, Strumienie przetwarzasz
  41. 41. CPUs and hard drives are really good at sequential reading/writing Use it
  42. 42. I grom potężny pazurem swym nieboskłon na strzępy rozdarł trzeci jeździec się wyłonił A imię jego
  43. 43. synchronized
  44. 44. Z pozoru wszystko wygląda niewinnie %system Context switches Voluntary (IO wait, syscall*) Non voluntary (within time slice) pidstat ­w ­t ­I ­p {pid} jstack {pid}
  45. 45. Waiting Is waste
  46. 46. 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)
  47. 47. Compare-and-swap java.util.concurrent.atomic „transakcyjne” metody Copy on write Persistent data structures
  48. 48. Atomic operations are getting faster and faster With every new CPU But we are not there yet!
  49. 49. I wody z oceanów wystąpiły, A z nich bestie żarłoczne, Człowiekowi nieprzychylne czwarty jeździec się wyłonił A imię jego
  50. 50. Just In Time compiler
  51. 51. Adaptive runtime Based on profiling data Slower startup times Slower peek peformance (in some cases*)
  52. 52. JIT (Just in Time) HotSpot Vs AOT (Ahead of Time) (www.excelsiorjet.com)
  53. 53. Interpreter C1 compiler C2 compiler OSR (on stack replacement) deoptimization
  54. 54. Inlining mother of all optimizations C1 compiler inlines small methods -XX:MaxInlineSize=35 -XX:InlineSmallCode=2000 C2 compiler inlines „hot” methods -XX:FreqInlineSize=325
  55. 55. 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); } }
  56. 56. The easy part private, static and final The hard part Polimorphism Class hierarchy analisys Deoptimization Beware of megamorph
  57. 57. 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; }
  58. 58. Inline cache Inline depth Recursive inline
  59. 59. other optimizations remove redundant loads loop unrollling global value numbering intrinsic escape analisys
  60. 60. … And few others even more interesting lock elision lock coarsenning adaptive locking biased locking
  61. 61. But first few words about „fat” and „thin” locks
  62. 62. JVM uses futex A „mostly” userspace lock based on atomic value and wait queue Unless high contention which forces futex to use kernelspace mutex
  63. 63. WAT?
  64. 64. Daleko jeszcze?
  65. 65. 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
  66. 66. Let the eternal stream of byte code Flows through your body

×