Высокая загрузка процессора в Java-приложении - почему?
У меня есть Java-приложение (веб-приложение), которое порой демонстрирует очень высокую загрузку процессора (почти 90%) в течение нескольких часов. Эта команда Linux TOP
показывает это. При перезапуске приложения проблема исчезает.
Итак, чтобы исследовать:
Я беру Thread Dump, чтобы найти, какие потоки делают. Несколько потоков находятся в состоянии 'RUNNABLE'
, в некоторых других состояниях. При повторном использовании Thread Dumps я вижу некоторые потоки, которые всегда присутствуют в состоянии 'RUNNABLE'
. Таким образом, они кажутся виновниками.
Но я не могу точно сказать, какой поток зацикливает процессор или перешел в бесконечный цикл (тем самым вызывая высокую загрузку процессора).
Журналы не обязательно помогают, так как код нарушения может не записывать ничего.
Как мне исследовать - какая часть приложения или что-нить вызывает высокую загрузку процессора? - Любые другие идеи?
Ответы
Ответ 1
Если профайлер не применим в вашей настройке, вы можете попытаться определить поток, следующий за шагами в этот пост.
В принципе, есть три шага:
- запустите
top -H
и получим PID потока с самым высоким ЦП.
- преобразуйте PID в hex.
- найдите поток с соответствующим HEX PID в дампе потока.
Ответ 2
Вы можете стать жертвой проблемы с сборкой мусора.
Когда вашему приложению требуется память, и он становится низким на том, что он сконфигурировал для использования сборщика мусора, будет работать часто, который потребляет много циклов процессора.
Если он не сможет собрать что-либо, ваша память останется низкой, поэтому она будет запущена снова и снова.
Когда вы повторно развертываете приложение, память очищается, и сбор мусора не будет происходить больше, чем требуется, поэтому загрузка процессора остается низкой, пока она не будет полностью заполнена.
Вы должны проверить, нет ли утечки памяти в приложении и что она хорошо сконфигурирована для памяти (проверьте параметр -Xmx
, см. Что представляет собой Java-вариант -Xmx?)
Кроме того, что вы используете в качестве веб-фреймворка? JSF много полагается на сеансы и потребляет много памяти, считайте себя апатридом больше!
Ответ 3
Ваш первый подход должен заключаться в том, чтобы найти все ссылки на Thread.sleep и проверить, что:
-
Сон - это правильная вещь - вы должны использовать какой-то механизм ожидания, если это возможно - возможно, осторожное использование BlockingQueue
поможет.
-
Если спать правильно, что вы делаете, вы спите в течение необходимого количества времени - это часто очень сложный вопрос для ответа.
Самая распространенная ошибка в многопоточном дизайне - это полагать, что все, что вам нужно делать, когда вы ожидаете, что что-то произойдет, - это проверить его и некоторое время спать в узком цикле. Это редко является эффективным решением - вы всегда должны пытаться wait
для возникновения.
Второй наиболее распространенной проблемой является цикл без сна. Это еще хуже и немного легче отслеживать.
Ответ 4
В течение этих пиковых значений процессорного времени, как выглядит пользовательская загрузка? Вы говорите, что это веб-приложение, поэтому преступники, которые приходят на ум, являются проблемами использования памяти. Например, если вы храните много вещей в сеансе, и количество сеансов становится достаточно высоким, сервер приложений начнет обманывать. Это также случай, когда GC может ухудшить ситуацию в зависимости от используемой вами схемы. Более подробная информация о приложении и конфигурации сервера была бы полезной, указывая на большее количество идей отладки.
Ответ 5
В дампе потока вы можете найти номер строки, как показано ниже.
для основного потока, который в настоящее время работает...
"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)**