Pokazywanie postów oznaczonych etykietą pomiar. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą pomiar. Pokaż wszystkie posty

czwartek, 30 czerwca 2011

Java: pomiar użycia pamięci

Wracamy do misji tego bloga. Ostatnio aż za dużo było pisania o tematach nawet nie do końca około informatycznych, więc czas nieco nadrobić. Blog ten miał dostarczać przede wszystkim rozwiązań problemów, których odszukanie mnie zajęło sporo czasu. Co ważne większość tych rozwiązań było przeze mnie znalezionych przede wszystkim na stronach niepolskojęzycznych. Zdaje mi się, że któryś temat kiedyś pochodził ze strony w języku rosyjskim. To musiałem być zdesperowany.

Dzisiaj rozwiązanie problemu pobrania informacji na temat ilości pamięci użytej przez naszą aplikację. Do pary kiedyś opisałem kwestię pomiaru czasu w języku Java (co na dodatek zapoczątkowało pewną serię).

poniedziałek, 26 października 2009

ASM: pomiar czasu wykonania kodu

Tak sobie co jakiś czas sprawdzam statystyki mojego bloga i okazuje się, że ludzie trafiają tu szukając rozwiązania problemu mierzenia czasu w assemblerze. Do tego jeszcze dwóch ciekawych rzeczy się dowiedziałem. Po pierwsze nie ma w sieci po polsku dobrze rozwiązanego tego problemu, albo nie ma go w ogóle, a po drugie mój blog pojawia się w wynikach wysoko przy tych poszukiwaniach. W tej sytuacji pozostało mi tylko odszukać rozwiązanie i opisać je samemu.

Aby więc zmierzyć czas wykonania kodu w assemblerze należy skorzystać z real-time clock wbudowanego w naszą maszynę i obsługiwanego przez BIOS. Niestety ma to 'urządzenie' pewną wadę. Mianowicie jego przerwanie generowane jest w stałych, stosunkowo dużych odstępach czasu, a dokładnie 55ms. Bez wątpienia nie nada się to do mierzenia czasu wykonania pojedynczych operacji.

Odczyt z RTC można wykonać korzystając z przerwania  1Ah i jego funkcji 00h. W wyniku w CX:DX otrzymujemy liczbę taktów od północy, a takt jak pamiętamy ma 55ms. Do tego jeszcze w AL uzyskkamy informację czy system pracuje dłużej niż 24h. Czyli jeśli pracuje dłużej niż 24h, to AL=1. Dokładne dane na temat tego przerwania można znaleźć w The Art Of Assembly Language Programming.

Tak jak w przypadku każdego pomiaru czasu należy pobrać wartości przed badanym blokiem i po nim, a następnie pierwszą odjąć od drugiej. Tutaj widać 2 niedogodności:
  1. trzeba odjąć od siebie 2 podwójne słowa,
  2. pomiar może być niedokładny.
 Wiemy jednak, że liczba druga jest większa lub równa pierwszej, więc możemy odjąć od siebie liczby po słowie i nie martwić się o pożyczki, a co do drugiego problemu, to maksymalny błąd wyniesie 54ms, czyli możemy uznać, że będzie pomijalnie mały. Oczywiście to zależy od tego co mierzymy. Jak zmierzymy wykonanie jednej instrukcji, to błąd będzie na poziomie 100% i możemy te dane wyrzucić. Jak zawsze działać należy z głową.

Wnikliwy umysł zauważy jeszcze jeden możliwy problem. Jeśli w czasie naszego pomiaru następi północ, to dowiemy się tylko, że była. Jeśli wystąpi raz, to jeszcze możemy wyliczyć czas do jej wystąpienia od startu i wyliczyć cały pomiar. Jeśli wystapi więcej niż raz, to niestety cały pomiar możemy wyrzucić, bo nie dowiemy się ile razy wystąpiła. W tej sytuacji pozostaje nam tylko skorzystanie z zegara systemowego (CMOS), który niestety ma dokładność do 1s, ale przyda się do takich dużych pomiarów.

Obrazek pochodzi z Freies Magazine.

niedziela, 26 kwietnia 2009

Java: pomiar czasu wykonania kodu

"Czas to pieniądz" - powiedzenie stare jak świat. Aktualnie złożoność obliczeniowa algorytmów jest dużo ważniejsza niż ich złożoność pamięciowa. Nie zawsze możemy dokładnie wyliczyć złożoność obliczeniową. Możemy na szczęście wykonać szybki pomiar czasu wykonania naszego kodu dla przykładowych danych.

Na polskojęzycznych stronach znaleźć można oczywiście różne metody oparte często na klasie Time. My skorzystamy bezpośrednio z klasy System i jednej metody statycznej.

Metoda:
System.currentTimeMillis();

Zwraca nam aktualny czas w milisekundach. Nie ma wielkiej potrzeby analizować wykonania kodu z dokładnością do nanosekundy. Milisekundy w zupełności starczą. Jak więc użyć tej metody? To bardzo proste: pobieramy czas przed, czas po i odejmujemy je od siebie.

long start=System.currentTimeMillis();
//długie obliczenia
long stop=System.currentTimeMillis();
System.out.println("Czas wykonania:"+(stop-start));

Jak nie trudno zauważyć jest to bardzo proste w użyciu. Oczywiście pokusić się można o bardziej zaawansowany kod wykorzystujący przy okazji filozofię OOP. Zainteresowanych takim wykorzystaniem tego kodu odsyłam do strony gdzie sam znalazłem te informacje w języku angielskim: How to measure execution time.

Można mierzyć czas w odcinkach. Na przykład gdy najpierw kalkulujemy, a potem rysujemy, to możemy zmierzyć czas całościowo i czas obu etapów. Pojawia się oczywiście problem błędu spowodowanego przez pobranie czasu z systemu. Na szczęście przy dużych liczbach obliczeń czas wywołania tej metody można uznać za pomijalnie mały. Doradzam nie nadużywać tej metody jak każdej innej. Pomijalnie mały czas dla odpowiedniej liczby powtórzeń stanie się niedopuszczalnie duży i nasz pomiar czasu wykonania stanie się niedokładny. Mówiąc prościej: na pewno nie mierzymy w ten sposób czasu trwania każdej iteracji pętli jednocześnie mierząc czas trwania wszystkich iteracji. Różnica sumy i całego pomiaru może nas zaskoczyć.

Obrazek pochodzi z The Uber Review.