2013-04-04 20 views
23

Mam aplikację Java (opartą na Internecie), która czasami wykazuje bardzo wysokie wykorzystanie procesora (prawie 90%) przez kilka godzin. Komenda Linux TOP pokazuje to. Po ponownym uruchomieniu aplikacji problem znika.Wysokie wykorzystanie procesora w aplikacji java - dlaczego?

więc zbadać:

biorę zrzutu wątku, aby znaleźć to, co robią wątki. Kilka wątków znajduje się w stanie 'RUNNABLE', niektóre w kilku innych stanach. Wykonując powtarzające się zrzuty wątków, widzę pewne wątki, które są zawsze obecne w stanie 'RUNNABLE'. Wydaje się, że są winowajcami.

Ale nie jestem w stanie stwierdzić z całą pewnością, który wątek przerywa procesor lub wszedł w nieskończoną pętlę (powodując w ten sposób wysoki pobór mocy procesora).

Logi niekoniecznie pomagają, ponieważ kolidujący kod może się nie rejestrować.

Jak zbadać - Jaka część aplikacji lub jakiego wątku powoduje wysokie wykorzystanie procesora? - Jakieś inne pomysły?

+0

Czy już próbować profilera? – andreapier

+2

Twoje zrzuty nici powinny również pokazywać, gdzie w kodzie są te wątki Runnable podczas zrzutu. Musisz zajrzeć tam w swoim kodzie. Wątki IIRC "działające" mogą czekać na I/O i nie zajmują CPU, ale jest wcześnie i nadal karmię swoją kawę. –

+0

andreapier> Chociaż może nie być możliwe użycie Profiler w środowisku Prod, ale czy Profiler powie, który wątek wyłapuje procesor? – Jasper

Odpowiedz

31

Jeśli profiler nie ma zastosowania w konfiguracji, możesz spróbować zidentyfikować wątek wykonując następujące czynności w kroku this post.

Zasadniczo istnieją trzy etapy:

  1. run top -H i uzyskać PID nici z najwyższej CPU.
  2. przekształcić PID na heks.
  3. poszukaj wątku z pasującym HEX PID w zrzucie wątku.
+0

jak osiągnąć to samo w oknach? – dom

1

Twoje pierwsze podejście powinno być, aby znaleźć wszelkie odniesienia do Thread.sleep i sprawdzić czy:

  1. Sen jest właściwa rzecz do zrobienia - trzeba zastosować jakiś mechanizm poczekać, jeśli to możliwe - nawet ostrożnego korzystania z BlockingQueue może pomóc.

  2. Jeśli śpisz jest, co należy zrobić, czy śpisz przez odpowiedni czas - często jest to bardzo trudne pytanie.

Najczęstszym błędem w wielowątkowych konstrukcji jest wierzyć, że wszystko, co trzeba zrobić, gdy czeka na coś się stanie to sprawdzić za nią i spać przez jakiś czas w ciasnej pętli. To rzadko jest skuteczne rozwiązanie - zawsze powinieneś spróbować, aby wystąpił w nim wait.

Drugim najczęstszym problemem jest pętla bez spania. Jest to jeszcze gorsze i nieco trudniejsze do wyśledzenia.

+0

'Thread.sleep' nie zużywa cykli procesora, prawda? – skirsch

+1

@skirsch - nie, nie jest - ale zwykle jest używany zamiast blokowania i blokowanie jest lepsze. – OldCurmudgeon

1

Podczas tych szczytowych czasów pracy procesora, jakie jest obciążenie użytkownika? Mówisz, że jest to aplikacja internetowa, więc sprawcami, którzy przychodzą na myśl, są problemy z wykorzystaniem pamięci. Jeśli na przykład przechowujesz wiele rzeczy w sesji, a liczba sesji będzie wystarczająco wysoka, serwer aplikacji zacznie wymyślać. Jest to również przypadek, w którym GC może pogorszyć sytuację w zależności od używanego schematu. Więcej informacji na temat aplikacji i konfiguracji serwera może pomóc w lepszym debugowaniu pomysłów.

+0

Wykorzystanie pamięci wydaje się być w porządku. – Jasper

8

Możesz być ofiarą problemu ze zbieraniem śmieci.

Gdy twoja aplikacja wymaga pamięci i zaczyna się obniżać to, do czego jest skonfigurowany, aby korzystać z garbage collector, często zużywa dużo cykli procesora. Jeśli nie będzie w stanie nic zebrać, pamięć pozostanie niska, więc będzie uruchamiana ponownie. Po ponownym wdrożeniu aplikacji pamięć zostaje wyczyszczona, a odśmiecanie nie nastąpi więcej niż jest to wymagane, więc wykorzystanie procesora pozostanie niskie do momentu ponownego pełnego zapełnienia.

Należy sprawdzić, czy nie ma możliwości wycieku pamięci w aplikacji i że jest dobrze skonfigurowany do pamięci (Sprawdź parametr -Xmx patrz What does Java option -Xmx stand for?)

Również co używasz jako ramy WWW? JSF bardzo polega na sesjach i zużywa dużo pamięci, uważając co najwyżej za bezpaństwowców!

+0

zatrzymać świat gc (co jest w zasadzie to, co masz na myśli) nie może działać wielowątkowo. Przekonasz się, że użyje on jednego z rdzeni w całości. –

+0

Wykorzystanie pamięci wydaje się być w porządku, oglądam to. Z Java Visual VM widzę, że aktywność GC (CPU) jest dość niska. – Jasper

1

W zrzucie można znaleźć numer linii jak poniżej.

dla głównego wątku, który jest obecnie w toku ...

"main" #1 prio=5 os_prio=0 tid=0x0000000002120800 nid=0x13f4 runnable [0x0000000001d9f000] 
    java.lang.Thread.State: **RUNNABLE** 
    at java.io.FileOutputStream.writeBytes(Native Method) 
    at java.io.FileOutputStream.write(FileOutputStream.java:313) 
    at com.rana.samples.**HighCPUUtilization.main(HighCPUUtilization.java:17)** 
Powiązane problemy