Blog (7)
Komentarze (49)
Recenzje (0)

Profiler w Netbeans

@jullo89Profiler w Netbeans10.02.2012 14:46

Jest wolna chwila, jest i wpis na blogu – tym razem o wydajności programów, a raczej o sprawdzaniu wydajności programów w środowisku Netbeans. Służy do tego Profiler, który dostarcza nam wielu cennych informacji o tworzonej przez nas aplikacji.

Ale co mamy sprawdzić? W tym przypadku możemy sprawdzić głównie wydajność programów pod względem zużycia pamięci, monitorowanie stanu wątków, wydajność procesora oraz możemy znaleźć „wąskie gardła”. Ja zwracam bardziej uwagę na możliwość monitorowania wątków i zużycie pamięci niż na wydajność procesora, ponieważ w tym przypadku wyniki są często (zawsze) bardzo przekłamane. Ale nie ma co się dziwić, ponieważ środowisko też potrzebuje czasu procesora na zebranie informacji o stanie pamięci, wątkach, załadowanych obiektach i klasach.

Do czego służy Profiler? Do poprawy naszej aplikacji, aby była wydajniejsza, doskonalsza, lepsza – tworząc programy/systemy należy dążyć do doskonałości chociaż już na starcie wiadomo, że jej nie osiągniemy. Dzięki temu narzędziu możemy się dowiedzieć jak wykonują się nasze wątki, ile czasu się wykonują, spędzają w trybie monitora lub są uśpione. Otrzymamy również informacje o ilości instancji obiektów poszczególnych klas oraz o tym ile pamięci zużywa nasza aplikacja. Większość informacji otrzymamy w formie wykresu lub tabelki. Wszystko ładnie, przejrzyście i zrozumiale.

Niestety nie poprawi za nas aplikacji. Może i to lepiej... więcej pracy dla programistów i projektantów(Ci też powinni być przy „profilowaniu” aplikacji).

Hmm co jeszcze... Może to, że tworząc program w Netbeans`ie możemy wyznaczać miejsca, w których chcemy uzyskać szczegółowych informacji o stanie pamięci i programie tj. sprawdzić ilość obiektów poszczególnych instancji itp. . Uruchamiając Profiler możemy określić co nas interesuje i jakie informacje mają być zbierane podczas wykonania tego procesu.

Dla zaawansowanych użytkowników Netbeansa istnieje możliwość uruchamiania aplikacji na innym komputerze co skutkuje szybszym wykonywanie procesu i zalecane jest dla dużych systemów z wiadomych przyczyn.

Tradycyjnie już skromny przykład

Zaczniemy od stworzenia wielowątkowej aplikacji- w tym wypadku aplikacja serwera. W tym celu otwieramy Netbensa, tworzymy nowy projekt. Nasza aplikacja będzie się składała z trzech klas: główna klasa z metodą "main", klasa będąca wątkiem serwera oraz klasa wątków obsługujących klientów.

Mój projekt wygląda mniej więcej tak, jak na obrazku poniżej.

Projekt
Projekt

Na początek kod wątku obsługi klienta ”ClientThread.java”.



package profilertest;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author michal
 */
public class ClientThread extends Thread{
    final private Vector clients;
    private Socket s;
    private static int id=0;
    
    public ClientThread(Socket s, Vector c){
        super("ClientThread"+id);
        id++;
        this.s=s;
        this.clients=c;
    }
    
       @Override
    public void run() {
        BufferedReader reader = null;
        BufferedWriter writer = null;
        try {
            reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
            writer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            String line = reader.readLine();
            writer.write(line + "\r\n");
            writer.flush();
            synchronized (clients) {
                clients.remove(this);
            }
        } catch (IOException ex) {
            Logger.getLogger(ClientThread.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                reader.close();
                writer.close();
                this.finalize();
            } catch (IOException ex) {
                Logger.getLogger(ClientThread.class.getName()).log(Level.SEVERE, null, ex);
            } catch (Throwable ex) {
                Logger.getLogger(ClientThread.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

Jak widać nic skomplikowanego klasa ta nie robi, ot po prostu odbiera napis od klienta i odsyła go, a na końcu usuwa obiekt z listy.

Poniżej przedstawiony został kod klasy ServerThread. Również za dużo się nie dzieje w tej klasie. Zwyczajnie akceptowane jest połączenie od klienta, tworzony wątek obsługi klienta i dodanie go do listy.


	package profilertest;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author michal
 */
public class ServerThread extends Thread {

    ServerSocket s;
    final int port = 16969;
    final Vector<ClientThread> clients = new Vector<ClientThread>();

    public ServerThread() {
        super("ServerThread");
    }

    @Override
    public void run() {
        try {
            System.out.println("Serwer wystartował");
            s = new ServerSocket(port);                             // tworzymy nowe gniazdo serwera
            while (true) {
                Socket s1 = s.accept();                             //akceptujemy nowe połączenie
                ClientThread ct1 = new ClientThread(s1, clients);   //tworzymy wątek klienta
                synchronized(clients){
                    clients.add(ct1);                               //dodajemy klienta do wektora
                }
                ct1.start();                                        //uruchamiamy wątek obsługi klienta
                System.out.println("Dodałem klietna");
            }
        } catch (IOException ex) {
            Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
            System.exit(-1);
        }
    }
}

Główna klasa z metodą „main” wygląda następująco:


	package profilertest;

public class ProfilerTest {
    
    public static void main(String[] args) {
       ServerThread server = new ServerThread();
       server.start();
    }
}

Chyba najdłuższa klasa w moim życiu :P Jak już mamy stworzony projekt serwera, to trzeba coś zrobić, aby przetestować nasz serwer i pokazać jak się sprawdza wydajność aplikacji w Netbeansie. Do tego tworzymy nowy projekt, z jedną klasa z metodą main. Kod został przedstawiony poniżej.


package profilerclient;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author michal
 */
public class ProfilerClient {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Vector<Thread> v = new Vector<Thread>();
        for(int i=0; i<100; i++){
            
           Thread t1 = new Thread("Client: "+i){//tworzymy nowy wątek
              public void run(){
                  BufferedReader reader = null;
                  BufferedWriter writer = null;
                    try {
                        Socket s = new Socket("localhost",16969);//łączymy się z serwerem
                        writer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
                        reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
                        writer.write(getName()+"\r\n");//wysyłamy nazwę wątku
                        writer.flush();
                        System.out.println(reader.readLine());//wypisujemy odebrany napis
                        reader.close();
                        writer.close();
                    } catch (UnknownHostException ex) {
                        Logger.getLogger(ProfilerClient.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (IOException ex) {
                        Logger.getLogger(ProfilerClient.class.getName()).log(Level.SEVERE, null, ex);
                    }
              }//koniec metody run  
            };
            v.add(t1);
        }//koniec pętli for
        
        for(int i=0; i<100; i++){
            v.elementAt(i).start();//startujemy wątek i-ty
        }
    }
}

Po skończeniu pracy z kodem powinniśmy otrzymać coś takiego lub podobnego jak na zrzucie poniżej.

Projekty-pliki
Projekty-pliki

Ok. Więc kod programu mamy już gotowy. Co teraz należy zrobić? Rozpocząć proces profilowania. Warto przed tym dokonać kalibracji środowiska JDK. W tym celu należy wybrać z menu „Profile” ->”Advanced Commands”-> „Run Profiler Calibration”, wybrać wersję JDK, którą używamy.

Kalibracja
Kalibracja
Wybór JDK
Wybór JDK

Następnie zaznaczamy nasz projekt jako główny(PPM, z menu kontekstowego wybieramy „Set as Main Project”) i z menu wybieramy „Profile” -> „Profile Main Project”. Powinno otworzyć się okno konfiguracyjne, w którym zaznaczamy interesujące opcje. Ja zrobiłem to tak, jak na zrzutach poniżej.

Ustawienia
Ustawienia
Ustawienia
Ustawienia
Ustawienia
Ustawienia

Przyszedł czas na uruchomienie przyciskiem „Run”. Po tym kroku po prawej stronie powinna pokazać się zakładka „Profiler”. Jeżeli z jakiegoś powodu nie pokazała się, można ją włączyć w menu „Windows”-> „Profiling”->”Profiler Control Panel”.

Profiler Control Panel
Profiler Control Panel

W panelu tym możemy zarządzać procesem sprawdzania aplikacji serwera, włączyć monitorowanie wątków, zużycie pamięci, pobierać „zrzuty pamięci” etc. . Zostało to przedstawione na rysunkach poniżej.

Przebieg wątków
Przebieg wątków
Wątki - Tabela
Wątki - Tabela
Wątek- Szczegóły
Wątek- Szczegóły

Trzeba pamiętać, że sprawdzając aplikację serwera trzeba uruchomić aplikację klienta. Na wykresie przebiegu wątków widać jak tworzone i uruchamiane były wątki obsługi klienta.

Pamięć - Stos
Pamięć - Stos
Wątki i załadowane klasy
Wątki i załadowane klasy
Pamięć
Pamięć

Jak zostało to pokazane można wiele się dowiedzieć z wykresów i tabel o wykonywaniu naszego programu. Ale to nie wszystko...

Podczas wykonywania programu tym sposobem możemy pobierać zrzuty pamięci przyciskiem „Take Snapshot” lub obserwować wyniki na żywo (jak ktoś potrafi szybko analizować :P). Dodatkowo możemy w programie ustawić miejsca w których ma się wykonać „snapshot”.

Jak to zrobić? Przechodzimy do kodu programu, klikamy prawym klawiszem myszy i z menu kontekstowego wybieramy „Profiling”->„Insert Profiling Point”. Pokaże się okno dodawania, w którym ustawiamy wszystkie parametry i kończymy dodając miejsce zrzutu. W jednej linijce możemy dodać 2 miejsca – przed wykonaniem instrukcji/metody i po wykonaniu. Wykorzystuję to do sprawdzania dużych metod, które długo się wykonują.

Dodawanie punktu zrzutu
Dodawanie punktu zrzutu
Ustawienia punktu
Ustawienia punktu
Ustawienia punktu
Ustawienia punktu

Następnie podczas wykonania procesu profilowania w oknie „Profiling Points” (jeżeli nie jest ono widoczne, należy je włączyć w menu: „Windows” -> „Profiling” -> „Profiling Points”), zostanie pokazany nasz punkt i przechwycony zrzut. Można go otworzyć klikająć PPM i wybierając opcję „Show Report”.

Profiling Points
Profiling Points

Trochę długi wpis wyszedł ze względu na zamieszczony kod programów oraz zrzuty ekranów. Dla osób szerzej zainteresowanych polecam strony: http://netbeans.org/features/java/profiler.html http://profiler.netbeans.org/ http://netbeans.org/kb/docs/java/profiler-intro.html Dziękuję za uwagę ;)

Szanowna Użytkowniczko! Szanowny Użytkowniku!
×
Aby dalej móc dostarczać coraz lepsze materiały redakcyjne i udostępniać coraz lepsze usługi, potrzebujemy zgody na dopasowanie treści marketingowych do Twojego zachowania. Twoje dane są u nas bezpieczne, a zgodę możesz wycofać w każdej chwili na podstronie polityka prywatności.

Kliknij "PRZECHODZĘ DO SERWISU" lub na symbol "X" w górnym rogu tej planszy, jeżeli zgadzasz się na przetwarzanie przez Wirtualną Polskę i naszych Zaufanych Partnerów Twoich danych osobowych, zbieranych w ramach korzystania przez Ciebie z usług, portali i serwisów internetowych Wirtualnej Polski (w tym danych zapisywanych w plikach cookies) w celach marketingowych realizowanych na zlecenie naszych Zaufanych Partnerów. Jeśli nie zgadzasz się na przetwarzanie Twoich danych osobowych skorzystaj z ustawień w polityce prywatności. Zgoda jest dobrowolna i możesz ją w dowolnym momencie wycofać zmieniając ustawienia w polityce prywatności (w której znajdziesz odpowiedzi na wszystkie pytania związane z przetwarzaniem Twoich danych osobowych).

Od 25 maja 2018 roku obowiązuje Rozporządzenie Parlamentu Europejskiego i Rady (UE) 2016/679 (określane jako "RODO"). W związku z tym chcielibyśmy poinformować o przetwarzaniu Twoich danych oraz zasadach, na jakich odbywa się to po dniu 25 maja 2018 roku.

Kto będzie administratorem Twoich danych?

Administratorami Twoich danych będzie Wirtualna Polska Media Spółka Akcyjna z siedzibą w Warszawie, oraz pozostałe spółki z grupy Wirtualna Polska, jak również nasi Zaufani Partnerzy, z którymi stale współpracujemy. Szczegółowe informacje dotyczące administratorów znajdują się w polityce prywatności.

O jakich danych mówimy?

Chodzi o dane osobowe, które są zbierane w ramach korzystania przez Ciebie z naszych usług, portali i serwisów internetowych udostępnianych przez Wirtualną Polskę, w tym zapisywanych w plikach cookies, które są instalowane na naszych stronach przez Wirtualną Polskę oraz naszych Zaufanych Partnerów.

Dlaczego chcemy przetwarzać Twoje dane?

Przetwarzamy je dostarczać coraz lepsze materiały redakcyjne, dopasować ich tematykę do Twoich zainteresowań, tworzyć portale i serwisy internetowe, z których będziesz korzystać z przyjemnością, zapewniać większe bezpieczeństwo usług, udoskonalać nasze usługi i maksymalnie dopasować je do Twoich zainteresowań, pokazywać reklamy dopasowane do Twoich potrzeb. Szczegółowe informacje dotyczące celów przetwarzania Twoich danych znajdują się w polityce prywatności.

Komu możemy przekazać dane?

Twoje dane możemy przekazywać podmiotom przetwarzającym je na nasze zlecenie oraz podmiotom uprawnionym do uzyskania danych na podstawie obowiązującego prawa – oczywiście tylko, gdy wystąpią z żądaniem w oparciu o stosowną podstawę prawną.

Jakie masz prawa w stosunku do Twoich danych?

Masz prawo żądania dostępu, sprostowania, usunięcia lub ograniczenia przetwarzania danych. Możesz wycofać zgodę na przetwarzanie, zgłosić sprzeciw oraz skorzystać z innych praw wymienionych szczegółowo w polityce prywatności.

Jakie są podstawy prawne przetwarzania Twoich danych?

Podstawą prawną przetwarzania Twoich danych w celu świadczenia usług jest niezbędność do wykonania umów o ich świadczenie (tymi umowami są zazwyczaj regulaminy). Podstawą prawną przetwarzania danych w celu pomiarów statystycznych i marketingu własnego administratorów jest tzw. uzasadniony interes administratora. Przetwarzanie Twoich danych w celach marketingowych realizowanych przez Wirtualną Polskę na zlecenie Zaufanych Partnerów i bezpośrednio przez Zaufanych Partnerów będzie odbywać się na podstawie Twojej dobrowolnej zgody.