Archive for category Java

Wyświetlenie parametrów Javy

Maszyna wirtualna Javy pozwala na ustawienie wielu różnych parametrów podczas uruchamiania, które moją wpływ na jej działanie. Pozwalają one m.in. na optymalizację pracy GC czy też związane z wielkością zajmowanej pamięci.

Jednym z parametrów jest AggressiveOpts, który pozwala na włączenie różnych parametrów optymalizacyjnych, które mogą zostać włączone w kolejnym wydaniu JVM. Warto jednak pamiętać, że wraz z każdym wydanie JVM lista tych opcji może się zmienć a ciężko znaleźć informację, jakie parametry są aktualnie używane.

Z pomocą tutaj przychodzą dwie opcje JVM:

  • PrintFlagsFinal – pozwala ona na wyświetlenie wartości wszystkich dopuszczalnych opcji
  • UnlockDiagnosticVMOptions – daje dostęp do dodatkowych opcji konfiguracyjnych

I tak listę wszystkich parametrów wraz z ich wartościami można obejrzeć przy pomocy polecenia:

java -XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions -version

A lista dla włączonej optymalizacji AggressiveOpts:

java -XX:+AggressiveOpts -XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions -version

Lista jest dosyć spora, więc prościej będzie zobaczyć po prostu różnice pomiędzy uruchomieniem JVM z i bez parametru AggressiveOpts:

diff <(java -XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions -version ) \
   <(java -XX:+AggressiveOpts -XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions -version )

W wersji JVM 1.6.26 wyświetli listę 6 różnych opcji, których ustawienie się różni. Łatwo także sprawdzić, czym się różni uruchomienie JVM z parametrem server oraz bez.

Dla ułatwienia analizy różnic, zamiast polecenia diff można użyć np. vimdiff:

vimdiff <(java -XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions -version ) \
   <(java -XX:+AggressiveOpts -XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions -version )

Źródła

Tags: ,

Instalacja Oracle Javy w Ubuntu Natty (11.04)

Standardowo w Ubuntu Java w wersji od Oracla (czyli dawana Sunowska) jest dostępna w repozytorium partner. Jednak w przypadku Ubuntu Natty (w wersji alfa) niestety jej tam jeszcze nie ma, prawdopodobnie zostanie umieszczona już po premierze wersji stabilnej. Na szczęście, łatwo można ją zainstalować przy wykorzystaniu dodatkowych repozytoriów, wystarczy wydać polecenie:

sudo add-apt-repository ppa:ferramroberto/java
sudo apt-get update

I zainstalować Javę:

sudo apt-get install sun-java6-jdk

Tags:

JMeter – budowa planu testu aplikacji stworzonej przy użyciu JBoss Seam, część 2

Druga część wpisu poświęconemu tworzeniu przy użyciu JMeter planu testów aplikacji napisanej za pomocą szkieletu JBoss Seam.

Przygotowanie testu do obsługi aplikacji napisane w JBoss Seam

Można teraz spróbować uruchomić test. Jeżeli testujemy aplikację napisaną w JBoss Seam, prawdopodobnie żadna strona nie zostanie wczytana (można to potwierdzić np. patrząc na zawartość pliku localhost_access_log) a serwer aplikacji wyrzuci stos wyjątków mówiącymi, że nie można odzyskać widoku. Spowodowane jest to tym, że Seam zapisuje na stronach oraz często w URL lub w wysyłanych formularzach dodatkowe wartość, które określają nazwę danego widoku raz numer konwersacji. Można sobie z tym poradzić, ale wymaga to dodatkowej pracy nad testem.

Trzeba będzie sobie poradzić z dwoma elementami: widokiem oraz konwersacją.

  • ViewState

    W przypadku widoku należy po kolej przejrzeć w aplikacji JMeter każde zapytanie, które zostanie wysłane do serwera aplikacji. Należy odszukać te strony, które zawierają w parametrach odwołanie do ciągu znakowego: javax.faces.ViewState. Powinna być tam określona wartość tego parametru, w moim przypadku było to j_id1:j_id2. W moim przypadku wywołanie to znajdowało się na drugiej stronie, w której następowało logowanie do aplikacji.

    JMeter - ViewState

    JMeter - ViewState

    Po identyfikacji właściwej strony należy należy teraz odszukać wywołanie poprzednie. Wartość dla parametru javax.faces.ViewState jest ustawiana w poprzednim wywołaniu, więc tam należy tę wartość przechwycić. Można to zrobić dodając do strony poprzedzającej to wywołanie komponent o nazwie Regular Expression Extractor, znajdujący się w menu Post Processors i go odpwiednio skonfigurować:

    • Name: ViewState Extractor – nazwa komponentu
    • Reference Name: VIEWSTATE – nazwa zmiennej, która będzie użyta do podstawienia wartości
    • Regular Expression: id="javax.faces.ViewState" value="([^"]*)" – wyrażenie regularne, które będzie użyte do pobranie właściwej wartości
    • Template: $1$
    • Match No.: 1
    JMeter - ViewState Extractor

    JMeter - ViewState Extractor

    Teraz jeszcze należy odpowiednio ustawić wartość dla parametru javax.faces.ViewState. Czyli trzeba otworzyć stronę na której występowało odwołanie do parametru i zmienić jego wartość na odwoła nie do zmiennej ${VIEWSTATE}.

    JMeter - konfiguracja zmiennej VIEWSTATE

    JMeter - konfiguracja zmiennej VIEWSTATE

    Jeżeli odwołanie do parametru javax.faces.ViewState występuje także na innych stronach, to także trzeba będzie takie zmiany wprowadzić. W moim przypadku wywołanie występowało na 5 stronach.

  • Konwersacje

    Konwersacje są jedną z włąściwości szkieletu JBoss Seam wyróżniającego go spośród innych rozwiązań (więcej na ten temat można znaleźć w manualu: Conversations and workspace management). W aplikacji Seamowej można zauważyć, że duża część linków zawiera dodatkowy parametr o nazwie conversationId czy też cid. Określa on numer określonej konwersacji, i wymaga także odpowiedniego potraktowania przez narzędzie testujące.

    Sposób radzenia sobie z konwersacjami jest podobny jak przy problemie z ViewState: należy odszukać wszystkie wystąpienia danej konwersacji i odpowiednio zmienić je na wywołania zmiennej.

    • najpierw należy zidentyfikować nazwę parametru używanego przez aplikację, może to być np. conversationId lub cid
    • odszukać wystąpienia tego parametru, powinien być przekazywany przy użyciu linku, czyli metodą GET, w moim przypadku jest to czwarta strona, wyświetlająca produkt:

      JMeter - wywołanie conversationId

      JMeter - wywołanie conversationId

    • należy do poprzedniej strony (analogicznie jak w przypadku ViewState) dodać komponent Regular Expression Extractor i go odpowiednio skonfigurować:
      • Name: ConversationID Extractor – nazwa komponentu
      • Reference Name: CID – nazwa zmiennej, która będzie użyta do podstawienia wartości
      • Regular Expression: conversationId=(\d+) – wyrażenie regularne, które będzie użyte do pobranie właściwej wartości
      • Template: $1$
      • Match No.: 1
      JMeter - ConversationID Extractor

      JMeter - ConversationID Extractor

    • odszukać wystąpienia danej konwersacji na następnych stronach i za wartość podstawić zmienną ${CID}:

      JMeter - konfiguracja zmiennej CID

      JMeter - konfiguracja zmiennej CID

    • powyższe kroki trzeba powtórzyć dla każdego numeru konwersacji (czyli jak zmienia się jej numer, to należy użyć wyrażenia regularnego do jego uzyskania, i następnie podstawiać tę wartość na następnych wywołaniach strony), w moim przykładzie należało użyć wyrażenia regularnego 3 razy i podmienić na zmienną 8 wartości

Po powyższych zmianach można uruchomić test i powinien już zadziałać bez problemów.

Uruchomienie testu

Ostatnim elementem testu będzie uruchomienie go w kilku wątkach oraz konfiguracja JMetera tak, aby używał do logowania kont różnych użytkowników.

Za zarządzanie użytkownikami odpowiada kontroler User Parameters. Pozwala on na zdefiniowanie użytkowników, jacy mogą zostać użyci w trakcie testu.

W ramach tego komponentu należy zdefiniować nazwę zmiennej która będzie używana do podstawienia za login oraz hasło użytkownika. W kolejnych kolumnach należy zdefiniować wartości dla tych zmiennych.

W przypadku aplikacji DVD Store występuje pięciu użytkowników o nazwach od user1 do user5, wszyscy z hasłem pasword. Definicja dla nich może wyglądać następująco:

JMeter - definicja użytkowników

JMeter - definicja użytkowników

Należy jeszcze zmodyfikować odpowiednio proces logowania do aplikacji, i zamiast wysyłania wartości w formularzu, wstawić odpowiednie zmienne JMeter:

JMeter - modyfikacja formularza logowania

JMeter - modyfikacja formularza logowania

Ostatnim elementem będzie uruchomienie większej ilości wątków i przetestowanie aplikacji. Można to zrobić w ramach komponentu Thread Group. W nim ustala się następujące parametry:

  • Number of Threads – ilość jednocześnie uruchamianych wątków, jeden wątek odpowiada jednemu użytkownikowi, jeżeli wątków będzie więcej niż zdefiniowanych użytkowników, to od nowa brany jest do logowania pierwszy użytkownik i potem następni
  • Ramp-Up Period – po jakim czasie wszystkie wątki mają działać, czyli ustawienie tu wartości na 5 sekund przy 5 wątkach spowoduje, że każdy wątek będzie uruchamiany co sekundę
  • Loop Count – ilość powtórzeń testów

Przykładowa konfiguracja może wyglądać tak:

JMeter - definicja sposobu uruchamiania testu

JMeter - definicja sposobu uruchamiania testu

Pozostaje teraz zdefiniować obciążenie serwera, uruchomić test i oglądać jak wygląda obiciążenie i kiedy serwer przestanie odpowiadać na zapytania.

JMeter - wyniki testu

JMeter - wyniki testu

Na koniec przygotowany plan testów dla aplikacji: Plan testu DVD Store.

Źródła

Tags: , ,

JMeter – budowa planu testu aplikacji stworzonej przy użyciu JBoss Seam, część 1

Ostatnimi czasy musiałem przygotować test wydajności dla aplikacji stworzonej przy użyciu szkieletu JBoss Seam. I okazało się, że nie do końca jest to takie trywialne. Poniżej opis, jak przygotować plan testu dla takiej aplikacji (oczywiście, spokojnie można go także użyć do budowy testu dla dowolnej aplikacji webowej).

Wpis składa się z dwóch części:

Oprogramowanie

W trakcie konstruowania testu używałem następujących aplikacji:

  • JMeter 2.3.4
  • JBoss EAP 5.1
  • JBoss DVD Store – aplikacja przykładowa dostarczana z biblioteką JBoss Seam 2.2.1

Przed przystąpieniem do budowy testu należy aplikację DVD Store zainstalować w serwerze aplikacyjnym.

Jeżeli będziemy się łączyli bezpośrednio z serwerem aplikacyjnym (np. używają linku http://localhost:8080/seam-dvdstore, to warto jeszcze dodać do niego możliwość logowania przychodzących połączeń HTTP. Może to się przydać, aby sprawdzić czy wszystko, czy nie występują jakieś błędy. Można to zrobić modyfikując plik $JBOSS_HOME//server/default/deploy/jbossweb.sar/server.xml. Należy w nim odkomentować nastepujący linie (więcej informacji na ten temat można znaleźć we wpisie Logowanie przychodzących połączeń HTTP w serwerze JBoss AS i Apache Tomcat):

80
81
82
83
<valve className="org.apache.catalina.valves.AccessLogValve"
   prefix="localhost_access_log." suffix=".log"
   pattern="common" directory="${jboss.server.log.dir}"
   resolveHosts="false" />

Plik z logiem będzie znajdował się w katalogu z logami: $JBOSS_HOME//server/default/log/localhost_access_log.DATA.log.

Zebranie danych do testowania

Pierwszym krokiem będzie zebranie stron, na których będzie wywoływany test. Można to zrobić na dwa sposoby:

  • zdefiniować wywołanie każdej strony ręcznie
  • użyć modułu proxy, który umożliwi nagranie sesji przy użyciu przeglądarki

Ponieważ drugi sposób będzie szybszy, to za jego pomocą nagramy sesję przeglądarki. JMeter udostępnia odpowiedni komponent, który działa jak serwer proxy i pozwala przechwycić żądania z przeglądarki. Konfiguracja jest prosta:

  • w JMeter należy dodać następujące komponenty:
    • do Test Plan komponent Thread Groupp – pozwala on na konfigurację przebiegu testu: ilość użytkowników, uruchomionych wątków, co ma się dziać w momencie wystąpienia błędu
    • do Thread Group dodać kontroler Recording Controller – zostaną w nim zapisane wszystkie przechwycone żądanie z komponentu proxy
    • do WorkBench dodać komponent HTTP Proxy Server – to jest nasz serwer proxy, pozwala on na konfiguracja kilku zachowań, teraz najważniejsz będzie port na którym zostanie on uruchomiony. W domyślnej konfiguracji jest to port 8080, które jest zajęty przez proces JBossa, należy więc zmienić go na jakiś inny, np. 9000.

      Wybór portu dla HTTP Proxy Server

      Wybór portu dla HTTP Proxy Server

  • skonfigurować odpowiednio przeglądarkę internetową, tak aby korzystała z serwera proxy. W przypadku Firefoksa powinno wyglądać to mniej więcej tak:
    Konfiguracja serwera proxy w Firefoksie

    Konfiguracja serwera proxy w Firefoksie

    Należy zwrócić uwagę na pole No Proxy for, domyślnie znajduje się tam wartość localhost, co może uniemożliwić nagranie sesji, jeżeli serwer JBoss jest uruchamiany na maszynie lokalnej.

Teraz czas na pobranie kilku stron, które będą używane następnie w trakcie testu. Należy jeszcze włączyć serwer proxy: w komponencie HTTP Proxy Server należy wybrać przycisk Start. W przypadku aplikacji DVD Store można wykonać takie kroki:

  • połączyć się ze stroną http://localhost:8080/seam-dvdstore/home
  • można zalogować się na konto wybranego użytkownika, w tym przypadku będzie to użytkownik user1
  • następnie obejrzeć jedną, dwie płyty
  • dodać płytę do koszyka i złożyć zamówienia
  • wylogować się

Te kroki powinny spowodować, że w aplikacji JMeter pojawi się pod komponentem Record Controler szereg zapytań o strony. Można zauważyć, że znajdują się tam wszystkie wywołania HTTP które wygenerowała przeglądarka, czyli łącznie z pobraniem obrazków, arkuszy stylów czy skryptów JavaScript. W moim przypadku skasowałem te wpisy. W przypadku gdy chcemy pobierać dodatkowe elementy strony, można w ramach zapytania o stronę w JMeter zaznaczyć opcję Retrive All Embedded Resources from HTML files.

W moim przypadku nagrana sesja wygląda następująco:

Nagrana sesja zapytań HTTP

Nagrana sesja zapytań HTTP

Uporządkowanie testu

Nagrane zapytania do serwera można teraz uporządkować wg funkcji które wykonują oraz trzeba jeszcze dodać kilka dodatkowych komponentów do projektu.

  • HTTP Cookie Manager – pozwala on na zarządzanie ciasteczkami, które są ustawiane przez badaną stronę
  • Graph Results – tworzy wykres w trakcie uruchamianie testu, można także dodać jakieś inne elementy, które będą zbierały dane z testu
  • Simple Controller – dodanie kilku (w tym przypadku 4) kontrolerów, które pozwolą na pogrupowanie zapytań do serwera
  • usunąć komponent Record Component

Grupowanie nie ma wpływu na sam test, ale na pewno zwiększy przejrzystość poszczególnych elementów testu.

Po uporządkowaniu zapytań, wygląda to następująco:

JMeter - grupowanie zapytań

JMeter - grupowanie zapytań

Źródła

Tags: , ,

Użycie dużych rozmiarów strony w JVM

W Javie istnieje możliwość zwiększania wydajności działania aplikacji poprzez zmianę sposobu użycia pamięci. Istnieje możliwość użycia Huge Memory Pages. Pozwalają one na użycie przez aplikację stron pamięci o większym rozmiarze niż standardowe 4kB (np. w przypadku Linuksa o rozmiarze 2048kB).

Użycie takich stron pozwala na zmniejszenie ilości mapowań dokonywanych przez TLB (Translation lookaside buffer). Niestety, przynajmniej w przypadku Linuksa przed użyciem takiej pamięci należy odpowiednio skonfigurować system operacyjny, czyli zarezerwować odpowiedni obszar pamięci, który zostanie użyty przez aplikacje. Trzeba pamiętać, że będzie on miał nastepujące właściwości:

  • obszar pamięci o dużych rozmiar stron będzie dostępny tylko dla aplikacji, które potrafią i chcą z niego korzystać (czyli jeżeli przeznaczymy za dużo pamięci na ten obszar, może zabraknąć RAMu dla innych aplikacji działających w ramach systemu operacyjnego)
  • pamięć ta nigdy nie zostanie zapisanie w pamięci tymczasowej (swap)
  • aplikacja musi mieścić się w całości w ramach tego obszaru, więc warto pamiętać że pamięć zajmowana przez JVM to jest suma dwóch wartości, definiowanych przez parametry -Xmx oraz -XX:MaxPermSize

Konfiguracja systemu operacyjnego Linuks


Konfigurację Huge Pages może zostać wykonana na działającym systemie, ale w przypadku za dużej fragmentacji pamięci może się nie powieść. W zawiązku z tym po zapisaniu zmian w pliku /etc/sysctl.conf przydatny może byc restart serwera.

Pierwszym krokiem będzie zdefiniowanie maksymalnego obszaru pamięci, jak ma zostać przeznaczony dla JVM. Najłatwiej zrobić to, umieszczając w pliku /etc/sysctl.conf następujący zapis:

73
kernel.shmmax = 1073741824

Wartość dla parametru należy podać w bajtach, ja zdefiniowałem ją na 1GB (1024 * 1024 * 1024). Parametr ten definiuje maksymalny obszar pamięci jaki za zostać przeznaczony dla aplikacji, ale wymagana jest jeszcze zdefiniowanie faktycznej ilości stron pamięci, jaka zostanie użyta. Robi się to przy użyciu parametru:

74
vm.nr_hugepages = 512

Rozmiar pojedynczej strony pamięci można sprawdzić przy użyciu plecenia:

grep Hugepagesize /proc/meminfo

Kolejnym krokiem będzie utworzenie specjalnej grupy w systemie operacyjnych, której członkowie będą mieli możliwość korzystania z tej specjalnej pamięci:

groupadd hugepgs

Teraz trzeba jeszcze poznań numer GID tej grupy:

grep hugepgs /etc/group

W moim przypadku będzie to numer 1005.

Teraz jeszcze należy poinformować system, że członkowie tej grupy będą mieli możliwość zapisywania do pamięci:

75
vm.hugetlb_shm_group = 1005

Dodajmy użytkownika jboss do zdefiniowanej grupy:

usermod -aG hugepgs jboss

Ostatnim krokiem będzie możliwości blokowania stron przez danego użytkownika. Robi się to w pliku /etc/security/limits.conf poprzez umieszczenie takiego wpisu:

61
62
jboss soft memlock unlimited
jboss hard memlock unlimited

Tym sposobem system operacyjny jest już skonfigurowany poprawnie, więc pozostaje uruchomić maszynę wirtualną tak, aby wykorzystała dostępną pamięć z dużymi rozmiarami strony. Robi się to przekazując parametr -XX:+UseLargePages w momencie uruchamiania JVM.

W przypadku serwera aplikacji JBoss najlepiej jest dodać parametr -XX:+UseLargePages w pliku konfiguracyjnym run.conf w miejscu definiowania zmiennej środowiskowej JAVA_OPTS. Po tym kroku można już uruchomić serwer.

Ilość zużytych bloków pamięci można sprawdzić przy użyciu komendy:

cat /proc/meminfo | grep -i pages

Źródła

Tags: ,