środa, 19 listopada 2014

Quick&Easy : Very simple CRUD application based on : Spring Boot + Thymeleaf + Webjars

Kilka postów temu dowiedzieliśmy się  jak stworzyć prosty CRUD oparty na Spring Boot +jsp.
Dziś coś szybkiego i równie łatwego, czyli CRUD zbudowany na Thymeleaf (w poście pt :" Dispel your security concerns - Spring Security part2 (mongoDB,Thymeleaf,boot) ". Każdy miał okazje spotkać się oficjalnie na tym blogu z Thymeleaf właśnie chyba w powyższym poście.
Teraz dodamy sobie funkcjonalność webjars czyli resources odpowiedzialne na frontend, które są w jednym miejscu i to spakowane w paczce jar. Jest to bardzo wygodne a zarazem wprowadza porządek do kodu.



Webjars to w naszym przypadku Twitter Bootstrap - bo nie znam się na css oraz js a chce, żeby strona miała trochę bajerów i była fajnie ostylowana oraz
JQuery - bo czasem potrzeba jakiegoś mechanizmu z AJAX.

Chce aby strona była w duchu i18n a dzięki springowi to nic trudnego. Aplikacja na potrzeby tego posta po prostu dodaje, edytuje, kasuje i wyświetla prosty słownik państw i ich kodów.

W następnych postach wyjaśnię czym są poniższe pojęcia na przykładzie kodu :
1.Redirect after POST choć to jest użyte już tej aplikacji
2. Black list @InitBinder
3. White list @InitBinder
4. Bean validation : JSR 303 i pewnie jeszcze wiele innych :)

Zaczynamy :
1. Webjars : 
 
Mały update w konfiguracja dzięki dodaniu :
ThymeLeaf header :
Konfiguracja dla Thymeleafa serwowana przez Spring Boota.
2. i18n :

Konfiguracja jest prosta :
Wskazujemy położenie plików z wiadomościami, informacje na temat locale zapisujemy w cookie, localeChangeInterceptor pozwala na zmianę języka w trakcie działania aplikacji : ?lang=en / ?lang=pl messageSource.setUseCodeAsDefaultMessage(true) - jeśli nie wyedytowaliśmy odpowiedniego klucza w pliku z properties użyj klucza jaka wiadomości, da nam to tyle, że uchroni nas przed wyrzuceniem exception dotyczącego nieznalezionego message'u dla danego kodu wiadomości.
Tip : Jak chcesz możesz zrobić swoją własną implemetację MessageSource np trzymać wiadomości w bazie oraz je cache'ować co pozwoli np na edycję kodów i wiadomości w trybie rzeczywistym, czasem też lepiej utrzymywalnym niż w pliku .properties

3.ThymeLeaf :

W plikach .html dobieramy się do messages poprzez znacznik th:text='#{code}':
4.DS configuration :


Efekt :










































Podsumowanie :
Prosty CRUD jak na załączonych screenshotach. Fajne efekty podświetlania pól oraz pozycjonowanie na stronie czy użyteczna górna belka z menu to zasługa Twitter Bootstrapa oraz JQuery. Thymeleaf to świetny silnik szablonów i na ten czas tyle trzeba wiedzieć. Webjars trzyma w ryzach wszystkie css i js, które dostajemy od zewnętrznych dostawców.
Baza H2 pozwala na przeglądanie danych przez klienta z przeglądarki.
JPA + Spring Data to prosty sposób na DAO.
Kod znajdziesz tutaj .


niedziela, 16 listopada 2014

Introduction to increase performance application based on JVM - part 2 - basic elements

Dziś kontynuujemy wprowadzenie do zwiększenia wydajności w aplikacjach opartych na JVM. Dzisiejszy post będzie skupiał się na VM runtime - czyli uruchomieniowym środowisku JVM stanowiącym pomost pomiedzy JIT a GC oraz dostarczającym funkcjonalości oraz API dla powyższych.
HotSpot VM można podzielić na trzy elementy :
   - VM runtime
   - JIT (client/server)
   - GC 
       - serial (szeregowy) 
       - throughput  (przepustowościowy)
       - CMS  (równoczesny)
       -  G1



Poprzedni post sygnalizował potrzebę monitoringu na warstwie systemu operacyjnego. Wymienione zostały podstawowe narzędzia wystarczające do zbierania danych i statystyk z dostępnych zasobów jak :
  - CPU
  - Memory
  - I/O
  - Network

Rysunek przedstawia poszczególne obszary możliwego tuningu wydajnościowego. Przez kolejne posty będziemy przechodzić przez poszczególne obszary.
W niektórych firmach admin DBA będzie miał odpowiedzialność dostrajania bazy, w innych będzie to musiał robić administrator odpowiedzialny za sprzęt czy serwery jak database server czy application server. Mogą występować też permutacje tych zależności. Wszystko zależy od profilu firmy, więc nie wykluczone, że w niektórych przypadkach będzie odpowiadał za wszystko programista/projektant/architekt


Powiedzieliśmy o możliwych problemach, które możesz napotkać jak : 
 - wolno działająca aplikacja
 - znaczący spadek wydajności postępujący w czasie (przyrost danych, rosnące zużycie pamięci itd)
 -  małe wycieki pamięci - impakt na wydajność
 - przestoje GC
 - duże wycieki pamięci generujące OutOfMemoryException a tym samym wydalenie się całego serwera
 - czasowe skoki procesora powodujące , że Twoja aplikacja przestaje odpowiadać na jakiekolwiek bodźce
 - inne zachowanie się aplikacja pod znaczącym obciążeniem a inne w przypadku małego obciążenia (response time)
 - problemy, które uaktywniają się na produkcji a na środowisku testowym były niezauważalne.

Poniższy wykres pamiętam, ze starej już książki pt :
Pro Java EE 5 Performance Management and Optimalization
obrazuje on zależność pomiędzy :
  - wykorzystaniem zasobów
  - przepustowością
  - czasem odpowiedzi dla końcowego użytkownika
  - zwiększeniem użycia aplikacji przez użytkowników

Chciałem go tutaj umieścić bo obrazuje bardzo fajnie te zależności, oraz pozwala zrozumieć jak Twoja aplikacja będzie reagowała na zmianę obciążenia.






















źródło : http://taas.inapp.com/?q=performance-testing

Ok, gdzie popełniliśmy błąd ? -  Zrozumienie JVM to dobra podstawa do eliminacji części tym problemów.


HotSpot JVM architecure :





























źródło : http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html


 Co nam daje JVM ?
  - przenośność między platformami dzięki kodowi bajtowemu
  - optymalizację w czasie wykonywania -  JIT
    - analiza ucieczki (escape analysis)
    - method inlining
    - wybór pomiędzy stertą a stosem (on stack replacement)
    - dynamiczna deoptymalizacja (dynamic deoptymalization)
   - zarządzanie pamięcią
   - security

Jeśli patrzymy na aplikację pod pryzmatem wydajności i skalowalności powinniśmy wiedzieć jak działa HotSpot VM.


VM Runtime zapewnia wspólny interfejs oraz usługi zarówno dla JIT jak i GC oraz :
  - zarządzanie wątkami
  - JNI
  - kontrola cyklu życia
  - analiza argumentów wywołania
  - obsługa wyjątków
  - class loader - ładowanie klas
  - byte code interpeter 
  - obsługa fatal errors

W VM Runtime możemy ustawić szereg ustawień lub zmienić  ich wartości domyślne.

-X - wersja standardowa dla opcji/ustawień
-XX - wersja deweloperska dla opcji/ustawień

( - ) - wyłącza daną opcję
( + ) - włącza daną opcję 

przykład : JAVA_OPTS=-verbose:gc -Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

  Flagi zostały podzielone na cztery grupy  : 
     - behavioral options - podstawowe zachodzania dla VM
     - GC options - zachowania w obrębie GC
     - Performance tuning options - użyteczne dla konfiguracja pod kontem  wydajności
     - debugging options - umożliwiające śledzenie, wyświetlanie oraz zbieranie informacji o działaniu HotSpot VM 

Główne flagi dla jvm runtime znajdziesz :  tutaj

Kontrola cyklu życia - to kontrola nad uruchamianiem (launcher) oraz wyłączaniem VM.

> java - launcher
    Czynności wykonywane są w kolejności :
       - analiza wiersza poleceń (argumenty)
       - określenie rozmiaru stery i stosu jeśli nie zostały wyszczególnione użyte zostaną ustawienia domyślne. Określenie trybu JIT (server/client)
      - utworzenie classpath
      - wyodrębnienie Main-Class z jara
      - szereg zdarzeń w ramach wywołania metody JNI_CreateJavaVM
      - załadowanie Main-Class w działającej już instancji VM
     
> javaws - sieciowy laucher dla apletów

Class Loading - VM ładuje klasy, mapuje klasy lub interfejsy na obiektu klas.
Ładowanie klas umożliwia API JAVY jak :
 - ClassLoader.loadClass()
 - Class.forName()
 - reflection API
 - JNI_FindClass

HotSpot może również sam inicjalizować ładowanie klas. Dzieje się to podczas fazy uruchamiania. Ładownie klasy wymaga wcześniejszego załadowania wszystkich nadklas oraz interfejsów.
Podczas weryfikacji pliku .class może okazać się , że wymagane będzie załadowanie jakiegoś zbioru klas.

Jak to działa ?
Plik .class  definiuje typ dla JVM określając pola, metody, dziedziczone informację,adnotacje itd. Klasa jest najmniejszą jednostką, która może być załadowana do JVM.
Korzystając z nazwy klasy lub jej interfejsu JVM szuka kodu binarnego w formie pliku .class, definiuje nazwę klasy oraz tworzy jej obiekt.

Cykl w jakim to wszystko następuje jest następujący : 

Class loadnig - > loaded - > linked -> verified

Po tych operacjach obiekt new Class jest dostępny dla systemu i nowa instancja obiektu może zostać stworzona.

Faza loaded pobiera za  pomocą strumieni danych kod danego pliku .class.
Obiekt klasy po tej fazie nie jest w pełni rozwinięty, a klasa nie jest gotowa do użytku.

Faza linked dzieli się na 3 fazy :
   - verification - potwierdzenie, że plik klasy jest zgodny z oczekiwaniami i że nie spowoduje błędów w czasie wykonywania programu. Sprawdzane też są lokalizacje innych typów referencyjnych występujących w klasie, aby upewnić się, że klasa jest gotowa do użycia. Testujemy symantykę pliku klasowego, symbole ze stałej puli, wykonywana jest też kontrola typów
Sprawdzamy czy np nie chcemy dziedziczyć po klasie finalnej czy metody statyczne są napisane przez klasy pochodne itd.
   Weryfikacja jest złożonym procesem i składają się na nią poszczególne etapy :
     - podstawowe sprawdzenie integralności (constants, static , final , etc )
     - sprawdzenie wszystkich metod pod kątem kontroli dostępu
    -  sprawdzenie czy te metody wywoływane są z prawidłową ilością parametrów i typów

Jeśli kod binarny reprezentujący interfejs lub klasę  nie może być odnaleziony dostajemy znany już wyjątek NoClassDefFound.

ClassLoader sprawdza również format dla pliku .class co może wprowadzić do :
 - ClassFormatError - jeśli uzna,że plik jest uszkodzony lub nie może być poprawnie zinterpretowany
 - UnsupportedClassVersionError - jeśli np klasy były skompilowane w kompilatorze dla innej wersji javy a odpalane już w innej wersji javy.
- ClassCircularityError - jeśli wystąpił błąd związany z hierarchią klas
- IncompatibleClassChangeError - jeśli bezpośredni interfejs nie jest interfejsem, lub nadklasa jest interfejsem.
- VerifyError - np gdy podczas kompilacji użyto innej biblioteki niż w czasie wykonania. 

  - upewnienie się czy bytecode nie próbuje manipulować stosem w sposób zagrażający bezpieczeństwu
  - upewnienie się czy zmienne są zainicjalizowane przed swoim użyciem
  - sprawdzenie czy zmienne mają przypisane odpowiednie typy i wartości
Kontrole te są wykonywane z powodów wydajnościowych, ponieważ umożliwiają pominięcie sprawdzeń w trakcie wykonywania, tworząc w ten sposób interpretowany kod mogący szybciej się uruchomić. Upraszczają także kompilację bytecode do kodu maszynowego w czasie wykonywania (JIT)

   -  preparation - polega na przydzielaniu pamięci i przygotowując zmienne statyczne do zainicjalizowania - ustawiane są ich wartości domyślne.

   -  resolution - sprawdzenie każdego typu referencyjnego znajdującego się w klasie. Nawet gdy typy nie są znane, mogą zostać załadowane.
W finalnej fazie wszystkie zmienne statyczne mogą być zainicjalizowane to samo dotyczy bloków statycznych w kodzie. Na samym końcu klasa jest gotowa do użycia.


Class loader delegation - przerzucenie odpowiedzialności za ładowanie klasy na inny class loader.  Ładowarki są zdefiniowane hierarchicznie. Główny class loader wyszukuje innych ładowarek w następującej kolejności :
  - bootstap class loader (ładuje klasy BOOTCLASSPATH, cześć VM ładuje podstawowe jary jak rt.jar i nie przeprowadza przy tym żadnej weryfikacji)
  - extension class loader (używana do ładowania standardowych jarów, zwykle uzupełniona o moduł security)
  - system class loader (domyślna ładowarka klas dla aplikacji, tak następuje ładowanie klas w większości środowisk SE)
  - custom class loader  - (użycie swojego własnego rozwiązania)

Obsługa błędów krytycznych

Często spotykanym błędem VM jest OutOfMemoryException.
Kiedy już on wystąpi konieczne jest zrozumienie przyczyny jego wystąpienia.
W przypadku awarii JVM tworzony jest dziennik błędów (error log file ) , o nazwie hs_err_pid{pid}.log. Domyślnie plik ten jest tworzony w katalogu w którym została uruchomiona maszyna wirtualna.
Plik ten na potrzeby analizy zawiera mapę pamięci.
Dzięki opcji -XX:ErrorFile możemy zdefiniować lokację tworzenia się pliku.
-XX:+HeapDumpOnOutOfMemoryError - włączenie generowania zrzutu sterty
-XX:HeapDumpPath=<path_to_heap_dump> - lokacja do pliku z zrzutem sterty

Przyczyny wystąpiena tego rozdzaju wyjątku mogą być następujące : 

  - brak fizycznej pamięci dostępnej dla JVM
  (Exception : java.lang.OutOfMemoryError: Unable to create new native thread)
 
  - brak pamięci w przestrzeni PermGen w wersjach od javy 7 w dół , lub metaspace dla javy 8 (może być spowodowany przez classloader)
   (Exception : java.lang.OutOfMemoryError: Metaspace)  - za wiele klas lub zbyt duże klasy ładowane do obszaru Metaspace
   (Exception : java.lang.OutOfMemoryError: PermGen space) - za wiele klas lub zbyt duże klasy ładowane do PermGen space
    więcej o obszarach PermGen i MetaSpace w następnym poście... 

  - aplikacja tworzy za dużo żywych obiektów by zmieściły się w stercie o danym rozmiarze (możliwe wycieki pamięci : kolekcje ! )
 (Exception : java.lang.OutOfMemoryError: Java heap space)

- JVM spędził za dużo czasu na wykonywanie GC  
 (Exception : java.lang.OutOfMemoryError: GC overhead limit exceeded)

Fajny opis wyjątków OutOfMemoryException znajdziesz  w cylku postów na tej stronie - polecam.

Jak wykrywać i jak przeciwdziałać tego typu sytuacją dowiesz się w następnych postach.

GC działanie i możliwe strategie - cdn ->

wtorek, 11 listopada 2014

Introduction to increase performance application based on JVM - part 1 - basic monitoring

Każdy programista chce aby jego produkt działał wydajnie i szybko. Wyobrażenie wydajniej aplikacji przyczyniło się w moim przypadku, iż na studiach uważałem, że język C++ jest jedynym właściwym językiem do budowy szybkich systemów czy aplikacji. Po pewnym czasie zobaczyłem ile trzeba się napierd...ć z tymi wskaźnikami, obsługą pamięci itd. To dla mnie był koszmar. Wtedy zorientowałem się , że w Javie jest JVM, który to większość problemów znanych mi z C rozwiązuje. Mało tego okazało się, że ogłoszeń o pracę jest dużo, dużo więcej i to był już gwóźdź do trumny mojej przygody z C czy C++.





Ale po kilku latach pracy z Javą okazało się, że znajomość działania GC czy samego JVM jest ważna i pozwala uwolnić więcej i więcej mocy z języków opartych na JVM.

 Wstęp do skalowania i profilowania omówiony był w tym poście.

Symptomy świadczące o problemach wydajnościowych to : 
 - wolne działanie aplikacji
 - aplikacja spowalnia z czasem lub po jakimś czasie występuje całkowity crash
 - wycieki pamięci wolne - powodujące spadek wydajności
 - wycieki pamięci na tyle duże, że powodują awarię systemu
 - czasowe skoki procesora lub zamrożenie działania aplikacji
 - problemy zdarzające się na systemach produkcyjnych nie mają swoich identyfikacji w środowisku testowym


Na co zwracać uwagę  :
 - staraj się pisać lub poprawiać algorytmy - tu z pomocą przyjdzie mechanizm microbenchmark'ów (JMH w następnych postach)

 - pisz mniej kodu
   Prawda jest taka, że mała ilość dobrze napisanego kodu będzie odpalała się szybciej niż duża ilość kodu tego samego standardu.
 Ponieważ :
  - czas kompilacja trwa dłużej - ma to wpływ na szybsze uruchomienie
  - alokacja pamięci i następnie cykle GC będą trwały mimowolnie dłużej dla większej liczby obiektów
  - ładowanie klas z dysku do JVM - opóźni start programu
  - więcej kodu to bardziej zapchany cache sprzętowy
  - dodanie każdego małego feature wpływa pośrednio na wydajność aplikacji
  Jeśli jakaś funkcjonalność nie jest potrzeba nie twórz jej a zbliżasz się jednocześnie do podejścia AGILE w wytwarzaniu softu
  - używaj lepszych i szybszych  bibliotek np zamień log4j na logback
    jackson mapper na fasterXml itd

 - baza danych prawie zawsze jest wąskim gardłem - pamiętaj o użyciu cache

 - użycie mechanizmy Stream z javy 8 pozwala na wykorzystanie wszystkich dostępnych rdzenie pocesora

  - monitoring logów JVM pozwala na analizę i eliminację przestojów GC

  - synchronizację i współdzielenie zasobów :
     -  immutable
     - zakładanie lock'ow na możliwie małym kawałku kodu
     - użycie kolekcji i mechnizmów z java.util.concurrent
    - Atomic... czyli mechanizm compare and swap z sun.misc.Unsafe
       (np unsafe.compareAndSwap)
   - zastosowanie operacji NIO nieblokujących - zamiast starych  mechanizmów I/O

  - używać dobrych praktyk - Effective Java czy Clean Code to podstawa

Twoja reakcja powinna iść w kierunku : monitoring -> profilowanie -> dostrajanie

Monitoring to bezinwazyjne zbieranie statystyk z środowisk produkcyjnych, przejściowych czy programistycznych. Najczęściej przyjmować będzie ono postać JMX bean'ów.

Profilowanie nastąpi już na wyraźną potrzebę zmian czy problemu zaobserwowanego w czasie fazy monitorowania czy testów wydajnościowo/obciężeniowych

Dostrajanie - na podstawie zebranych statystyk systemu oraz aplikacji czy kontenera na którym osadzona jest aplikacja podjęcie działania w celu eliminacji problemu i wypełnienia warunków uzgodnionych w SLA.


Wyróżniamy taki oto podział od samej góry kierując się do dołu : 
    - aplikacja J2EE
    - serwer aplikacyjny/kontener serwletów
    - JVM
    - OS
    - sprzęt (hardware)

Jeśli zaczynasz pracę nad aplikacją, która to wymaga restrykcyjnych wymagać wydajnościowych to zastanów się nad : 
- określeniem celi (SLA , parametry  aplikacji)
- przepustowością swojej aplikacji
- czasem odpowiedzi
- możliwością skalowania
- opóźnieniem pomiędzy żądaniem a jakimkolwiek reakcją na takie żądanie (max i min)
- liczbą użytkowników którzy będą jednocześnie korzystać z systemu
- czy częstotliwość oczyszczania pamięci ma wpływ na opóźnienie













Zastanów się również nad kompromisem między :
- czasem opóźnienia a przepustowością
- skalowalnością a wydajnością
- spójnością a dostępnością

Bardzo fajny przykład czytałem parę lat temu na jakimś amerykańskim blogu.
Chodziło o transport ale nie było powiedziane czego z Chicago do New York.
Jeśli chodziłoby o osobę wybrałbyś pewnie samolot (latency) , ale jeśli w grę wchodziłoby kilka ton węgla - wtedy pociąg byłby idealny (throughput)


Istnieją dwa podejścia do optymalizacji systemu : 

Top down  - sprawdzamy coraz niższe warstwy aplikacji w poszukiwaniu problemów oraz potencjalnych wąskich gardeł
(Stosowana przez developerów)
Testujemy aplikacją aby zbadać pod jakimś założonym obciążeniem pojawiają się problemy z wydajnością lub określić próg stabilnej i akceptowalnej pracy aplikacji w zgodności z SLA


Monitorujemy :
 - statystyki systemu operacyjnego
 - statystyki JVM
 - statystyki kontenera aplikacji

Na podstawie powyższych danych możemy przeprowadzić analizę wyników oraz regulację mechanizmu odzyskiwania pamięci.


Buttom up - zaczynamy od najniższej warstwy takiej jak zasoby sprzętowe : procesor, pamięć itd i idziemy wyżej
(Stosowana przez specjalistów od spraw wydajności , różne platformy , systemy operacyjne)

Poprawiamy wydajność aplikacji w stosunku do danej platformy czy systemu operacyjnego.
Kiedy nie ma możliwości przeprowadzenia zmian w kodzie źródłowym

Statystyki które  nas interesują to :
 - liczba instrukcji CPU niezbędnych do wykonania danego zadania (path lenght)
 - liczbę odwołań poza pamięcią cache (mniejsza liczba odwołań to większa wydajność, bo okres pobierania danych będzie krótszy)


optymalizacja obejmuje :
 - zmiana struktur danych - w tym samym bloku pamięci podręcznej
 - zmiana algorytmu szeregowania instrukcji CPU
 - optymalizacja magazynów danych, modyfikacji sprzętu, protokołów


Modyfikacje obejmują w tej metodzie głównie usprawnienie wykorzystania CPU.
Zmiana konstrukcji w kodzie źródłowym poprzez umieszczenie często używanych danych obok siebie może implikować zmniejszeniem czasu pobierania liczby odwołań poza CPU cache. Tutaj do akcji wkroczy często JIT

TIP : JIT - generacja bardziej efektywnego kodu w oparciu o zaistniałe warunki
(o JIT w następnych postach)


 CPU może być wykorzystywany przez :
  - użytkownika (user) -  czas w % jaki aplikacja spędza na wykonywaniu kodu aplikacji
  - jądro (kernel) - czas w % jaki aplikacja spędza na wykonanie kodu jądra
  - system (sys) - czas w % jaki aplikacja spędza na wykonanie dyrektyw systemu

Wysoka zajętość % czasu przez kernel lub sys może wskazywać na konflikty wejścia/wyjścia lub zbyt długą iteracje między tymi urządzeniami
Należy dążyć aby minimalizować ten czas gdyż może być on z powodzeniem wykorzystany na przetwarzanie kodu aplikacji.

IPC - (instructions per clock) - liczba instrukcji CPU przypadającej na cykl zegara
CPI - (cycle per instruction) - liczba cykli zegara przypadających na instrukcje

Oczekiwanie procesora spowodowane pobieraniem danych z pamięci podręcznej  określamy jako przestój (stall). Przestój występuje wtedy kiedy procesor wykonuje jakąś instrukcję i a dane, które są potrzebne do zakończenia jej nie są dostępne w rejestrze lub pamięci podręcznej procesora.
Marnujemy więc cykle na doładowanie danych, które to z punktu widzenia aplikacji powinny być już dostępne.



Monitorujemy CPU za pomocą programów :
 - System monitor
 - htop
 - top
 - vmstat vmstat [interval] [count]

  • Procs – r: Total number of processes waiting to run
  • Procs – b: Total number of busy processes
  • Memory – swpd: Used virtual memory
  • Memory – free: Free virtual memory
  • Memory – buff: Memory used as buffers
  • Memory – cache: Memory used as cache.
  • Swap – si: Memory swapped from disk (for every second)
  • Swap – so: Memory swapped to disk (for every second)
  • IO – bi: Blocks in. i.e blocks received from device (for every second)
  • IO – bo: Blocks out. i.e blocks sent to the device (for every second)
  • System – in: Interrupts per second
  • System – cs: Context switches
  • CPU – us, sy, id, wa, st: CPU user time, system time, idle time, wait time



vmstat -D   -> show system disk statistics
CPU Scheduler Run Queue - powstaje gdy jakieś lekkie procesy gotowe do uruchomienia czekają na swoje kolej. Jeśli jest więcej takich procesów niż procesorów w systemie takie procesy trafiają do kolejki oczekiwania na swoją kolej. Idealna sytuacja jest wtedy kiedy takich procesów jest mniej lub równo z procesorami wirtualnymi maszyny. Przyjmuje się, że czterokrotność liczby procesów w stosunku do procesorów może powodować widoczne spowolnienie systemu.
Głębokość kolejki wskazuje zatem na obciążenie systemu zadaniami

Skoro jesteśmy przy tym to należy zwrócić też uwagę, że zwiększenie liczby wątków czasem może przenieść odwrotny efekt niż zwiększenie wydajności systemu.
Najlepiej jak w przypadku mechanizmu Javy 8 Stream , który w przetwarzaniu równoległym tworzy tyle wątków ile procesów wirtualnych.

W przeciwnym razie system musi obsłużyć jakoś te wątki. Następują wtedy przełączenia kontekstu ma to wpływ na :
 - czyszczenie TLB 
 - zabrudzenia lub czyszczenie caches w procesorze

Przełączenia kontekstu sprawdzamy dzięki : 
cs - przełączanie kontekstu
Dobrowolne przełączanie kontekstu jest wtedy jak wykonywany wątek  dobrowolnie zwalnia CPU

 Koszt przełączenia kontekstu :
 źródło : how-long-does-it-take-to-make-context.html
  • Intel 5150: ~4300ns/context switch
  • Intel E5440: ~3600ns/context switch
  • Intel E5520: ~4500ns/context switch
  • Intel X5550: ~3000ns/context switch
  • Intel L5630: ~3000ns/context switch
  • Intel E5-2620: ~3000ns/context switch

si - ilość pamięci na stronach wchodzących
so - ilość pamięci na stronach wychodzących
r - głębokość kolejki planisty krótkoterminowego

id - idle time określa % czas bezczynności procesora
Mogą być tego następujące przyczyny  :
  - blokada wątków wewnątrz aplikacji
  - aplikacja czeka na odpowiedz np z synchronicznego WS-* czy z bazy danych
  - aplikacja poprostu nie ma nic do roboty

- pidstat - monitorujemy procesy lub konkretny proces


  pidstat -w  - statystyka mimowolnych przełączeń kontekstu
 cswch/s - Total number of voluntary context switches the task made per second.  A voluntary context switch occurs when a task blocks because it requires a resource that is unavailable.

nvcswch/s -  Total number of non voluntary context switches the task made per second.  A involuntary context switch takes place when a task executes for the duration of its time slice and  then  is
                     forced to relinquish the processor.

Mimowolne przełączanie kontekstu zachodzi wtedy gdy wykonywany wątek jest usuwany z uwagi na przekroczenie limitu czasu lub zostanie wywłaszczony na rzecz innego wątku o wyższym priorytecie.

Wysoki poziom tego parametru wskazuje na saturację wątków, czyli jest więcej wątków w systemie niż procesów,  które mogłby te wątki obsłużyć.
Odpowiada to kolumnie r w narzędziu vmstat czyli kolejce planisty krótkoterminowego

pidstat -s - monitorujemy stos (a do czego jest stos o tym potem :))

pidstat -d 2 - monitorujemy operacje I/O w interwale co 2 sek
pidstat -r 2 - monitorujemy wykorzystanie pamięci

- mpstat

%usr - Show the percentage of CPU utilization that occurred while executing at the user level (application).

%nice - Show the percentage of CPU utilization that occurred while executing at the user level with nice priority.

%sys - Show the percentage of CPU utilization that occurred while executing at the system level (kernel). Note that this does not include time spent servicing hardware and software interrupts.

%iowait - Show the percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request.

%irq - Show the percentage of time spent by the CPU or CPUs to service hardware interrupts.

%soft -Show the percentage of time spent by the CPU or CPUs to service software interrupts.

%steal - Show the percentage of time spent in involuntary wait by the virtual CPU or CPUs while the hypervisor was servicing another virtual processor.

%guest - Show the percentage of time spent by the CPU or CPUs to run a virtual processor.

%idle - Show the percentage of time that the CPU or CPUs were idle and the system did not have an outstanding disk I/O request.

  - sysstat - wymagana biblioteka dla iostat i vmstat

  - perf - monitorowanie procesów
   
  - nicstat  - ważne informację z poziomu monitorowania i przepustowości sieci (network bandwidth) lub wydajnością (network I/O performance).
   - iostat - wykorzystanie I/O
     iostat {interval } {how many time view result}
     Operacje I/O mają duży impakt na wydajność w szczególności jeśli mamy dużo zapisów lub odczytów małych ilości danych pochłania dużą ilość zasobów procesora (SYS/Kernel) , które można by było wykorzystać w inny sposób.

Powyższy wydruk pokazuje wykorzystanie procesora oraz operacje dyskowe na
każdym urządzeniu zamontowanym w systemie.
 źródło :  pomiar wydajności w linuxie
  • lk_wrtn/s: Indicate the amount of data written to the device expressed in a number of blocks per second.
  • Blk_read: The total number of blocks read.
  • Blk_wrtn: The total number of blocks written.
  • kB_read/s: Indicate the amount of data read from the device expressed in kilobytes per second.
  • kB_wrtn/s: Indicate the amount of data written to the device expressed in kilobytes per second.
  • kB_read: The total number of kilobytes read.
  • kB_wrtn: The total number of kilobytes written.
  • MB_read/s: Indicate the amount of data read from the device expressed in megabytes per second.
  • MB_wrtn/s: Indicate the amount of data written to the device expressed in megabytes per second.
  • MB_read: The total number of megabytes read.
  • MB_wrtn: The total number of megabytes written.
  • rrqm/s: The number of read requests merged per second that were queued to the device.
  • wrqm/s: The number of write requests merged per second that were queued to the device.
  • r/s: The number of read requests that were issued to the device per second.
  • w/s: The number of write requests that were issued to the device per second.
  • rsec/s: The number of sectors read from the device per second.
  • wsec/s: The number of sectors written to the device per second.
  • rkB/s: The number of kilobytes read from the device per second.
  • wkB/s: The number of kilobytes written to the device per second.
  • rMB/s: The number of megabytes read from the device per second.
  • wMB/s: The number of megabytes written to the device per second.
  • avgrq-sz: The average size (in sectors) of the requests that were issued to the device.
  • avgqu-sz: The average queue length of the requests that were issued to the device.
  • await: The average time (in milliseconds) for I/O requests issued to the device to be served. This includes the time spent by the requests in queue and the time spent servicing them.
  • svctm: The average service time (in milliseconds) for I/O requests that were issued to the device.
  • %util: Percentage of CPU time during which I/O requests were issued to the device (bandwidth utilization for the device). Device saturation occurs when this value is close to 100%.

Interesujące nas również parametry pamięci to : 
   - paging (stronicowanie)
   - swapping (wymiana stron)
     Następuje wtedy gdy jeśli aplikacja pobiera większa ilość pamięci niż dostępna pamięć fizyczna. Wtedy system korzysta pomocniczo z dysku to ma duży impakt na wydajność
   - locking (blokowanie) - analiza periodycznych zrzutów wątków (thread dumps) narzędzia to jvisualvm
   - context switching (przełączanie kontekstu) (mimowolne i dobrowolne)
     (narzędzie to : pidstat oraz vmstat)
   - thread migration  (migracja wątku) - migracja wątków wpływa na wydajność ponieważ po przełączeniu na inny rdzeń dane lub infomację o stanie gotowego do uruchomienia wątku mogą nie być już dostępne w pamięci podręcznej.


Monitoring Lock Contention - monitorowanie rywalizacji o blokady
Istnieje narzędzie pidstat w opcją -w podaje liczbę dobrowolnych przełączeń kontekstu dla wszystkich procesorów wirtualnych.

Jak obliczyć zmarnowane cykle zegara na przełączenia kontekstu ?
Bazując na informacjach zawartych w książce java performanceon multi-core platforms
temp = cswch/s  * 80 000 / liczba procesów wirtualnych
liczna_cykli = częstotliwość procesora
liczna marnowanych cykli to temp/liczba_cykli


Stare ale nadal aktualne informacje w postaci mind-maps :


Basic elements -> next



środa, 5 listopada 2014

Git bundle

Dziś trochę o git.
A dokładniej o bundle.  
Scenariusz jest np taki:
 1.Sieć nie działa a chcesz podesłać zmiany dla kolegów.
 2. Sieć może i działa ale istnieją powody bezpieczeństwa dla których to będzie lepiej dostarczyć zmiany innym kanałem np pendrive lub email +pgp.
Tutaj do akcji wchodzi git bundle.

Zadanie : kanał web jest nie dostępny z różnych powodów
Cel : Populacja zmian w repozytorium git w sposób przyrostowy



Tworzenie : git bundle create {some_repo.bundle} master = git push origin master

Odtworzenie danych : git clone {path/to/some_repo.bundle} -b {branch} {new_name}

Pobranie zmian przyrostowo : git pull {path/to/some_repo.bundle} {branch}

W główym repozytorium w którym pracuje tworzę git bundle: 
dla testów tworzę następny katalog : (a w nim wykonuje komende clone w celu odtworzenia całego repo)
Jeśli chce populować branch'a nie ma problemu :
Jeśli chce dociągnąć tylko ostatnie zmiany ze spreparowanego wcześniej bundle :